mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-10 15:08:14 +00:00
236 lines
9.2 KiB
C#
236 lines
9.2 KiB
C#
//
|
|
// (C) Copyright 2003-2014 by Autodesk, Inc.
|
|
//
|
|
// Permission to use, copy, modify, and distribute this software in
|
|
// object code form for any purpose and without fee is hereby granted,
|
|
// provided that the above copyright notice appears in all copies and
|
|
// that both that copyright notice and the limited warranty and
|
|
// restricted rights notice below appear in all supporting
|
|
// documentation.
|
|
//
|
|
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
|
|
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
|
|
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
|
|
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
|
|
// UNINTERRUPTED OR ERROR FREE.
|
|
//
|
|
// Use, duplication, or disclosure by the U.S. Government is subject to
|
|
// restrictions set forth in FAR 52.227-19 (Commercial Computer
|
|
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
|
|
// (Rights in Technical Data and Computer Software), as applicable.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.DB.ExtensibleStorage;
|
|
using Autodesk.Revit.UI;
|
|
|
|
namespace DynamicModelUpdate
|
|
{
|
|
|
|
/// <summary>
|
|
/// Updater to automatically move a section in conjunction with the location of a window
|
|
/// </summary>
|
|
public class SectionUpdater : IUpdater
|
|
{
|
|
internal SectionUpdater(AddInId addinID)
|
|
{
|
|
m_updaterId = new UpdaterId(addinID, new Guid("FBF3F6B2-4C06-42d4-97C1-D1B4EB593EFF"));
|
|
m_schemaId = new Guid("4DE4BE80-0857-4785-A7DF-8A8918851CB2");
|
|
}
|
|
|
|
// Registers itself with Revit
|
|
internal void Register(Document doc)
|
|
{
|
|
// create a window filter for the updater's scope
|
|
// we are only interested in two elements, one window and one section
|
|
// (for the sake of simplicity, we hard-coded the elements' unique Ids)
|
|
String windowUniqueId = "7f04899c-797b-4ad1-a9da-c6de1243ff83-00025ff6";
|
|
String sectionUniqueId = "4ca42fe1-e3e2-4bee-ab19-7d6e95cdf1bc-000261e8";
|
|
|
|
Element window = doc.GetElement(windowUniqueId);
|
|
if (window == null)
|
|
throw new Exception("Window was not found in the document.");
|
|
Element section = doc.GetElement(sectionUniqueId);
|
|
if (section == null)
|
|
throw new Exception("Section was not found in the document.");
|
|
|
|
// Setup collection of ids for the updater
|
|
List<ElementId> idsToWatch = new List<ElementId>();
|
|
m_windowId = window.Id;
|
|
idsToWatch.Add(m_windowId);
|
|
m_sectionId = section.Id;
|
|
|
|
UpdateInitialParameters(doc);
|
|
|
|
// Register and set a trigger for the section updater when the window changes
|
|
UpdaterRegistry.RegisterUpdater(this, doc);
|
|
UpdaterRegistry.AddTrigger(m_updaterId, doc, idsToWatch, Element.GetChangeTypeGeometry());
|
|
}
|
|
|
|
#region IUpdater members
|
|
|
|
// The Execute method for the updater
|
|
public void Execute(UpdaterData data)
|
|
{
|
|
try
|
|
{
|
|
Document doc = data.GetDocument();
|
|
FamilyInstance window = doc.GetElement(m_windowId) as FamilyInstance;
|
|
Element section = doc.GetElement(m_sectionId);
|
|
|
|
// iterate through modified elements to find the one we want the section to follow
|
|
foreach (ElementId id in data.GetModifiedElementIds())
|
|
{
|
|
if (id == m_windowId)
|
|
{
|
|
//Let's take this out temporarily.
|
|
bool enableLookup = false;
|
|
if (enableLookup)
|
|
m_schema = Schema.Lookup(m_schemaId); // (new Guid("{4DE4BE80-0857-4785-A7DF-8A8918851CB2}"));
|
|
|
|
Entity storedEntity = null;
|
|
storedEntity = window.GetEntity(m_schema);
|
|
|
|
//
|
|
// first we look-up X-Y-Z parameters, which we know are set on our windows
|
|
// and the values are set to the current coordinates of the window instance
|
|
Field fieldPosition = m_schema.GetField("Position");
|
|
XYZ oldPosition = storedEntity.Get<XYZ>(fieldPosition, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
|
|
TaskDialog.Show("Old position", oldPosition.ToString());
|
|
|
|
LocationPoint lp = window.Location as LocationPoint;
|
|
XYZ newPosition = lp.Point;
|
|
|
|
// XYZ has operator overloads
|
|
XYZ translationVec = newPosition - oldPosition;
|
|
|
|
// move the section by the same vector
|
|
if (!translationVec.IsZeroLength())
|
|
{
|
|
ElementTransformUtils.MoveElement(doc, section.Id, translationVec);
|
|
}
|
|
TaskDialog.Show("Moving", "Moving");
|
|
|
|
// Lookup the normal vector (i,j,we assume k=0)
|
|
Field fieldOrientation = m_schema.GetField("Orientation");
|
|
// Establish the old and new orientation vectors
|
|
XYZ oldNormal = storedEntity.Get<XYZ>(fieldOrientation, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
|
|
|
|
XYZ newNormal = window.FacingOrientation;
|
|
|
|
// If different, rotate the section by the angle around the location point of the window
|
|
|
|
double angle = oldNormal.AngleTo(newNormal);
|
|
|
|
// Need to adjust the rotation angle based on the direction of rotation (not covered by AngleTo)
|
|
XYZ cross = oldNormal.CrossProduct(newNormal).Normalize();
|
|
double sign = 1.0;
|
|
if (!cross.IsAlmostEqualTo(XYZ.BasisZ))
|
|
{
|
|
sign = -1.0;
|
|
}
|
|
angle *= sign;
|
|
if (Math.Abs(angle) > 0)
|
|
{
|
|
Line axis = Line.CreateBound(newPosition, newPosition + XYZ.BasisZ);
|
|
ElementTransformUtils.RotateElement(doc, section.Id, axis, angle);
|
|
}
|
|
|
|
// update the parameters on the window instance (to be the current position and orientation)
|
|
storedEntity.Set<XYZ>(fieldPosition, newPosition, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
|
|
|
|
storedEntity.Set<XYZ>(fieldOrientation, newNormal, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
window.SetEntity(storedEntity);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
TaskDialog.Show("Exception", ex.ToString());
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
public UpdaterId GetUpdaterId()
|
|
{
|
|
return m_updaterId;
|
|
}
|
|
|
|
public string GetUpdaterName()
|
|
{
|
|
return "Associative Section Updater";
|
|
}
|
|
|
|
public string GetAdditionalInformation()
|
|
{
|
|
return "Automatically moves a section to maintain its position relative to a window";
|
|
}
|
|
|
|
public ChangePriority GetChangePriority()
|
|
{
|
|
return ChangePriority.Views;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
// Setup routine: updates parameters of the window to the appropriate values on load
|
|
internal void UpdateInitialParameters(Document doc)
|
|
{
|
|
|
|
Transaction t = new Transaction(doc, "Update parameters");
|
|
t.Start();
|
|
|
|
|
|
SchemaBuilder builder = new SchemaBuilder(m_schemaId); //(new Guid("{4DE4BE80-0857-4785-A7DF-8A8918851CB2}"));
|
|
builder.AddSimpleField("Position", typeof(XYZ)).SetUnitType(UnitType.UT_Length);
|
|
builder.AddSimpleField("Orientation", typeof(XYZ)).SetUnitType(UnitType.UT_Length);
|
|
builder.SetSchemaName("WallPositionData");
|
|
builder.SetDocumentation("Two points in a Window element that assist in placing a section view.");
|
|
builder.SetVendorId("adsk");
|
|
builder.SetApplicationGUID(doc.Application.ActiveAddInId.GetGUID());
|
|
|
|
m_schema = builder.Finish();
|
|
|
|
t.Commit();
|
|
|
|
t.Start();
|
|
Field fieldPosition = m_schema.GetField("Position");
|
|
Field fieldOrientation = m_schema.GetField("Orientation");
|
|
|
|
FamilyInstance window = doc.GetElement(m_windowId) as FamilyInstance;
|
|
|
|
Entity storageEntity = new Entity(m_schema);
|
|
|
|
LocationPoint lp = window.Location as LocationPoint;
|
|
XYZ location = lp.Point;
|
|
|
|
storageEntity.Set<XYZ>(fieldPosition, location, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
|
|
XYZ orientation = window.FacingOrientation;
|
|
storageEntity.Set<XYZ>(fieldOrientation, orientation, DisplayUnitType.DUT_FEET_FRACTIONAL_INCHES);
|
|
window.SetEntity(storageEntity);
|
|
|
|
|
|
t.Commit();
|
|
}
|
|
|
|
// private data:
|
|
|
|
private Guid m_schemaId;
|
|
private UpdaterId m_updaterId = null;
|
|
private ElementId m_windowId = null;
|
|
private ElementId m_sectionId = null;
|
|
private Schema m_schema;
|
|
}
|
|
|
|
} |