/// <summary> /// Builds a group of displacement elements from a collection of element ids, and /// sets the displacement to be uniform in Z but vary in XY based on location. /// </summary> /// <param name="doc">The document.</param> /// <param name="ids">The collection of ids.</param> /// <param name="view">The view.</param> private void BuildDisplacementElementGroup(Document doc, ICollection <ElementId> ids, View view) { // The last element will be in the "parent" displacement element. (At least one element // must remain assigned to the parent, so all child displacements will be relative to the // parent's displacement.) Element lastElement = doc.GetElement(ids.Last <ElementId>()); XYZ parentDisplacedLocation = GetDisplacementXYFor(lastElement, XYZ.Zero); parentDisplacedLocation = MoveToElevation(parentDisplacedLocation, initialHeight); // All elements are added to the parent displacement element. DisplacementElement parent = DisplacementElement.Create(doc, ids, parentDisplacedLocation, view, null); m_displacementElements.Add(parent); int count = ids.Count; List <ElementId> childIds = new List <ElementId>(); List <ElementId> idsList = ids.ToList <ElementId>(); // Add all elements except the last one to child displacement elements for (int index = 0; index < count - 1; index++) { ElementId childId = idsList[index]; Element e = doc.GetElement(childId); XYZ displacedLocation = GetDisplacementXYFor(e, parentDisplacedLocation); // Setup id container for child DisplacementElement creation childIds.Clear(); childIds.Add(childId); DisplacementElement child = DisplacementElement.Create(doc, childIds, displacedLocation, view, parent); } view.HideElements(ids); }
/// <summary> /// Gets the XY displacement for a given element. /// </summary> /// <param name="element">The displacement element.</param> /// <returns>The displacement.</returns> private XYZ GetDisplacementXY(DisplacementElement element) { // If the element is a child, need to take into account the displacement of the parent. XYZ displacementDueToParent = XYZ.Zero; if (DisplacementElementIsChild(element)) { DisplacementElement parent = element.Document.GetElement(element.ParentId) as DisplacementElement; displacementDueToParent = parent.GetRelativeDisplacement(); } // Assume one element per displacement, use that element to get the displacement needed. ElementId id = element.GetDisplacedElementIds().First <ElementId>(); Element e = element.Document.GetElement(id); return(GetDisplacementXYFor(e, displacementDueToParent)); }
/// <summary> /// Initializes and fills the displacement table. /// </summary> /// <param name="displacements">Displacements from all found matches.</param> /// <param name="entryCount">The number of entries in the final table.</param> protected void CreateDisplacementTable(int[] displacements, int entryCount) { var distribution = CalculateDisplacementCoverage(displacements.Select(x => (double)x).ToArray(), entryCount); _displacementTable = new DisplacementElement[entryCount]; var displacementStart = 1; var codeBits = (int)Math.Log(distribution[0], 2); for (var i = 0; i < entryCount - 1; i++) { _displacementTable[i] = new DisplacementElement(codeBits, displacementStart); displacementStart += (short)(1 << codeBits); codeBits = (int)Math.Log(distribution[i + 1] - displacementStart, 2); } if (1 << codeBits != (int)distribution[entryCount - 1] - displacementStart) { codeBits++; } _displacementTable[entryCount - 1] = new DisplacementElement(codeBits, displacementStart); }
/// <summary> /// Identifies if the displacement element is a parent or a child. /// </summary> /// <param name="element"></param> /// <returns>True if the element is a child of another element.</returns> private static bool DisplacementElementIsChild(DisplacementElement element) { return(element.ParentId != ElementId.InvalidElementId); }