/// <summary> /// Add the 2D projection of the given arc /// to the current element outline union /// </summary> static public bool AddToUnion( Polygons union, VertexLookup vl, Clipper c, Arc arc) { IList <XYZ> pts = arc.Tessellate(); int n = pts.Count; Polygons faces = new Polygons(1); Polygon face2d = new Polygon(n); IntPoint a = vl.GetOrAdd(pts[0]); face2d.Add(a); for (int i = 1; i < n; ++i) { IntPoint b = vl.GetOrAdd(pts[i]); if (b != a) { face2d.Add(b); a = b; } } faces.Add(face2d); return(c.AddPaths(faces, PolyType.ptSubject, true)); }
/// <summary> /// Convert the curves to a polygon /// and add it to the union /// </summary> public bool AddToUnion( Polygons union, VertexLookup vl, Clipper c, List <LineSegment> curves) { Polygons polys = CreatePolygons(curves); return(c.AddPaths(polys, PolyType.ptSubject, true)); }
/// <summary> /// Return the union of the outermost room boundary /// loop projected onto the XY plane. /// </summary> static public bool AddToUnionRoom( Polygons union, List <LineSegment> curves, VertexLookup vl, Clipper c, IList <IList <BoundarySegment> > boundary) { int n = boundary.Count; Debug.Assert(0 < n, "expected at least one room boundary loop"); Polygons faces = new Polygons(n); Polygon face2d = new Polygon(boundary[0].Count); foreach (IList <BoundarySegment> loop in boundary) { // Outer curve loops are counter-clockwise face2d.Clear(); foreach (BoundarySegment s in loop) { IList <XYZ> pts = s.GetCurve().Tessellate(); IntPoint a = vl.GetOrAdd(pts[0]); face2d.Add(a); n = pts.Count; for (int i = 1; i < n; ++i) { IntPoint b = vl.GetOrAdd(pts[i]); if (b != a) { face2d.Add(b); a = b; } } faces.Add(face2d); } } return(c.AddPaths(faces, PolyType.ptSubject, true)); }
public StateMachine ToMachineModel() { var machine = new StateMachine(Name); var vertexLookup = new VertexLookup(); // First pass : state declarations foreach (var component in Components) { switch (component) { case StateDefinition stateDef: machine.AddChild(CreateState(machine, stateDef, vertexLookup)); break; default: // Ignore everything else in this pass break; } } // Second pass : internal and external transitions foreach (var component in Components) { switch (component) { case StateDefinition stateDef: HandleStateComponents(stateDef, vertexLookup); break; default: // Ignore everything else in this pass break; } } return(machine); }
private State CreateState(IVertex parent, StateDefinition stateDef, VertexLookup vertexLookup) { var state = new State(parent, stateDef.ShortName); vertexLookup.Add(state); foreach (var component in stateDef.Contents) { switch (component) { case StateDefinition childState: state.AddChild(CreateState(state, childState, vertexLookup)); break; default: // Ignore everything else in this pass break; } } return(state); }
/// <summary> /// Add the 2D projection of the given mesh triangles /// to the current element outline union /// </summary> static public bool AddToUnion( Polygons union, VertexLookup vl, Clipper c, Mesh m) { int n = m.NumTriangles; Polygons triangles = new Polygons(n); Polygon triangle = new Polygon(3); for (int i = 0; i < n; ++i) { MeshTriangle mt = m.get_Triangle(i); triangle.Clear(); triangle.Add(vl.GetOrAdd(mt.get_Vertex(0))); triangle.Add(vl.GetOrAdd(mt.get_Vertex(1))); triangle.Add(vl.GetOrAdd(mt.get_Vertex(2))); triangles.Add(triangle); } return(c.AddPaths(triangles, PolyType.ptSubject, true)); }
private void HandleStateComponents( StateDefinition stateDefinition, VertexLookup lookup) { var state = (State)lookup[stateDefinition.ShortName]; foreach (var component in Components) { switch (component) { case StateDefinition childStateDef: // already handled break; case ExternalTransition initialTrans when initialTrans.IsInitialTransition: // add initial transition break; default: // Ignore everything else in this pass break; } } }
/// <summary> /// Add the 2D projection of the given face /// to the current element outline union /// </summary> static public bool AddToUnion( Polygons union, VertexLookup vl, Clipper c, Face f) { IList <CurveLoop> loops = f.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > sortedLoops = ExporterIFCUtils.SortCurveLoops(loops); int n = loops.Count; Debug.Assert(0 < n, "expected at least one face loop"); Polygons faces = new Polygons(n); Polygon face2d = new Polygon(loops[0].NumberOfCurves()); //foreach( IList<CurveLoop> loops2 // in sortedLoops ) foreach (CurveLoop loop in loops) { // Outer curve loops are counter-clockwise if (loop.IsCounterclockwise(XYZ.BasisZ)) { face2d.Clear(); foreach (Curve curve in loop) { IList <XYZ> pts = curve.Tessellate(); IntPoint a = vl.GetOrAdd(pts[0]); face2d.Add(a); n = pts.Count; for (int i = 1; i < n; ++i) { IntPoint b = vl.GetOrAdd(pts[i]); if (b != a) { face2d.Add(b); a = b; } } } faces.Add(face2d); } } return(c.AddPaths(faces, PolyType.ptSubject, true)); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; if (null == doc) { Util.ErrorMsg("Please run this command in a valid" + " Revit project document."); return(Result.Failed); } ICollection <ElementId> ids = Util.GetSelectedElements(uidoc); if ((null == ids) || (0 == ids.Count)) { return(Result.Cancelled); } // Third attempt: create the element 2D outline // from element solid faces and meshes in current // view by projecting them onto the XY plane and // executing 2d Boolean unions on them. View view = doc.ActiveView; Options opt = new Options { View = view }; Clipper c = new Clipper(); VertexLookup vl = new VertexLookup(); List <LineSegment> curves = new List <LineSegment>(); Polygons union = new Polygons(); Dictionary <int, JtLoops> booleanLoops = new Dictionary <int, JtLoops>(ids.Count); foreach (ElementId id in ids) { Element e = doc.GetElement(id); GeometryElement geo = e.get_Geometry(opt); c.Clear(); vl.Clear(); union.Clear(); AddToUnion(union, curves, vl, c, geo); //AddToUnion( union, vl, c, curves ); //c.AddPaths( subjects, PolyType.ptSubject, true ); //c.AddPaths( clips, PolyType.ptClip, true ); bool succeeded = c.Execute(ClipType.ctUnion, union, PolyFillType.pftPositive, PolyFillType.pftPositive); if (0 == union.Count) { Debug.Print(string.Format( "No outline found for {0} <{1}>", e.Name, e.Id.IntegerValue)); } else { JtLoops loops = ConvertToLoops(union); loops.NormalizeLoops(); booleanLoops.Add(id.IntegerValue, loops); } } string filepath = Path.Combine(Util.OutputFolderPath, doc.Title + "_element_2d_boolean_outline.json"); JtWindowHandle hwnd = new JtWindowHandle(uiapp.MainWindowHandle); string caption = doc.Title + " 2D Booleans"; Util.ExportLoops(filepath, hwnd, caption, doc, booleanLoops); return(Result.Succeeded); }
/// <summary> /// Return the union of all outlines projected onto /// the XY plane from the geometry solids and meshes /// </summary> static public bool AddToUnion( Polygons union, List <LineSegment> curves, VertexLookup vl, Clipper c, GeometryElement geoElem) { foreach (GeometryObject obj in geoElem) { // Curve // Edge // Face // GeometryElement // GeometryInstance // Mesh // Point // PolyLine // Profile // Solid // Skip objects that contribute no 2D surface Curve curve = obj as Curve; if (null != curve) { Arc arc = curve as Arc; if (null != arc && arc.IsCyclic) { AddToUnion(union, vl, c, arc); } else if (curve.IsBound) { curves.Add(new LineSegment( vl.GetOrAdd(curve.GetEndPoint(0)), vl.GetOrAdd(curve.GetEndPoint(1)))); } continue; } Solid solid = obj as Solid; if (null != solid) { foreach (Face f in solid.Faces) { // Skip pretty common case: vertical planar face if (f is PlanarFace && Util.IsHorizontal(((PlanarFace)f).FaceNormal)) { continue; } AddToUnion(union, vl, c, f); } continue; } Mesh mesh = obj as Mesh; if (null != mesh) { AddToUnion(union, vl, c, mesh); continue; } GeometryInstance inst = obj as GeometryInstance; if (null != inst) { GeometryElement txGeoElem = inst.GetInstanceGeometry( Transform.Identity); // inst.Transform AddToUnion(union, curves, vl, c, txGeoElem); continue; } Debug.Assert(false, "expected only solid, mesh or instance"); } return(true); }
GetElementLoops( View view, ICollection <ElementId> ids) { Document doc = view.Document; Options opt = new Options { View = view }; Clipper c = new Clipper(); VertexLookup vl = new VertexLookup(); List <LineSegment> curves = new List <LineSegment>(); Polygons union = new Polygons(); Dictionary <int, JtLoops> booleanLoops = new Dictionary <int, JtLoops>(ids.Count); foreach (ElementId id in ids) { c.Clear(); vl.Clear(); union.Clear(); Element e = doc.GetElement(id); if (e is Room) { IList <IList <BoundarySegment> > boundary = (e as Room).GetBoundarySegments( new SpatialElementBoundaryOptions()); // Ignore all loops except first, which is // hopefully outer -- and hopefully the room // does not have several disjunct parts. AddToUnionRoom(union, curves, vl, c, boundary); } else { GeometryElement geo = e.get_Geometry(opt); AddToUnion(union, curves, vl, c, geo); } //AddToUnion( union, vl, c, curves ); //c.AddPaths( subjects, PolyType.ptSubject, true ); //c.AddPaths( clips, PolyType.ptClip, true ); bool succeeded = c.Execute(ClipType.ctUnion, union, PolyFillType.pftPositive, PolyFillType.pftPositive); if (0 == union.Count) { Debug.Print(string.Format( "No outline found for {0} <{1}>", e.Name, e.Id.IntegerValue)); } else { JtLoops loops = ConvertToLoops(union); loops.NormalizeLoops(); booleanLoops.Add(id.IntegerValue, loops); } } return(booleanLoops); }
//static List<ElementId> GetRoomBoundaryIds( // Room room, // SpatialElementBoundaryOptions seb_opt ) //{ // List<ElementId> ids = null; // IList<IList<BoundarySegment>> sloops // = room.GetBoundarySegments( seb_opt ); // if( null != sloops ) // the room may not be bounded // { // Debug.Assert( 1 == sloops.Count, "this add-in " // + "currently supports only rooms with one " // + "single boundary loop" ); // ids = new List<ElementId>(); // foreach( IList<BoundarySegment> sloop in sloops ) // { // foreach( BoundarySegment s in sloop ) // { // ids.Add( s.ElementId ); // } // // Skip out after first segement loop - ignore // // rooms with holes and disjunct parts // break; // } // } // return ids; //} /// <summary> /// Create a JtLoop representing the 2D outline of /// the given room including all its bounding elements /// by creating the inner room boundary loop and /// uniting it with the bounding elements solid faces /// and meshes in the given view, projecting /// them onto the XY plane and executing 2D Boolean /// unions on them. /// </summary> public static JtLoops GetRoomOuterBoundaryLoops( Room room, SpatialElementBoundaryOptions seb_opt, View view) { Document doc = view.Document; Options opt = new Options { View = view }; Clipper c = new Clipper(); VertexLookup vl = new VertexLookup(); List <LineSegment> curves = new List <LineSegment>(); Polygons union = new Polygons(); JtLoops loops = null; IList <IList <BoundarySegment> > boundary = room.GetBoundarySegments( new SpatialElementBoundaryOptions()); if (null != boundary) // the room may not be bounded { Debug.Assert(1 == boundary.Count, "this add-in currently supports only rooms " + "with one single boundary loop"); // Ignore all loops except first, which is // hopefully outer -- and hopefully the room // does not have several disjunct parts. // Ignore holes in the room and // multiple disjunct parts. AddToUnionRoom(union, curves, vl, c, boundary); // Retrieve bounding elements List <ElementId> ids = new List <ElementId>(); foreach (IList <BoundarySegment> loop in boundary) { foreach (BoundarySegment s in loop) { ids.Add(s.ElementId); } // Skip out after first segement loop - ignore // rooms with holes and disjunct parts break; } foreach (ElementId id in ids) { // Skip invalid element ids, generated, for // instance, by a room separator line. if (!id.Equals(ElementId.InvalidElementId)) { Element e = doc.GetElement(id); GeometryElement geo = e.get_Geometry(opt); AddToUnion(union, curves, vl, c, geo); bool succeeded = c.Execute(ClipType.ctUnion, union, PolyFillType.pftPositive, PolyFillType.pftPositive); if (0 == union.Count) { Debug.Print(string.Format( "No outline found for {0} <{1}>", e.Name, e.Id.IntegerValue)); } } } loops = ConvertToLoops(union); loops.NormalizeLoops(); } return(loops); }
/// <summary> /// Initialized the vertex & index buffers for this mesh scene /// </summary> public void ReInitialize() { if (m_noTexturing) { ReInitializeWithoutTexturing(); return; } // prepare vars m_coloredTrifans.Clear(); m_texturedTrifans.Clear(); // loop through the texturing info and determine for each of them what // type of decoration it is. m_decorations = new MeshDecoration[m_simpleMesh.TextureInfo.Length]; m_textures = new Texture[m_decorations.Length]; for (int i = 0; i < m_decorations.Length; i++) { m_decorations[i] = new MeshDecoration(m_simpleMesh.TextureInfo[i]); if (m_decorations[i].DecorationType == DecorationType.Texture) { Bitmap bmp = m_decorations[i].Texture.GetBitmap(); m_textures[i] = new Texture(m_device, bmp, 0, Pool.Managed); } } // we'll have to create two sets of index buffers: // one for textured trifans and one for colored trifans // we'll have to determine for each trifan to which of these it belongs List <VertexLookup> texturedVertexTable = new List <VertexLookup>(); List <VertexLookup> coloredVertexTable = new List <VertexLookup>(); List <ushort> texturedIndexList = new List <ushort>(); List <ushort> coloredIndexList = new List <ushort>(); for (int i = 0; i < (int)m_simpleMesh.SecondTrifanSet.TrifanCount; i++) { TrifanInfo trifan = m_simpleMesh.SecondTrifanSet.TrifanData[i]; bool drawSolidColor = false; drawSolidColor = (trifan.Flags & 0x04) == 0x04; // draw solid when this trifan is drawn using a solid color drawSolidColor = drawSolidColor || (m_decorations[(int)trifan.TextureIndex].DecorationType == DecorationType.SolidColor); if (drawSolidColor) { Color color = m_decorations[(int)trifan.TextureIndex].SolidColor; TrifanDrawInfo trifanInfo = new TrifanDrawInfo(); trifanInfo.IndexBufferStart = (ushort)coloredIndexList.Count; trifanInfo.PrimitiveCount = trifan.VertexCount - 2; for (int j = 0; j < trifan.VertexIndices.Length; j++) { VertexLookup lookup = new VertexLookup(trifan.VertexIndices[j], 0, color); ushort vertexIndex; if (!coloredVertexTable.Contains(lookup)) { coloredVertexTable.Add(lookup); } vertexIndex = (ushort)coloredVertexTable.IndexOf(lookup); coloredIndexList.Add(vertexIndex); } m_coloredTrifans.Add(i, trifanInfo); } else { TrifanDrawInfo trifanInfo = new TrifanDrawInfo(); trifanInfo.IndexBufferStart = (ushort)texturedIndexList.Count; trifanInfo.PrimitiveCount = trifan.VertexCount - 2; for (int j = 0; j < trifan.VertexIndices.Length; j++) { VertexLookup lookup = new VertexLookup(trifan.VertexIndices[j], trifan.UVIndex[j]); ushort vertexIndex; if (!texturedVertexTable.Contains(lookup)) { texturedVertexTable.Add(lookup); } vertexIndex = (ushort)texturedVertexTable.IndexOf(lookup); texturedIndexList.Add(vertexIndex); } m_texturedTrifans.Add(i, trifanInfo); } } // now create the actual index & vertex buffers // texture vb & ib if (texturedVertexTable.Count > 0) { m_vbTextured = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), texturedVertexTable.Count, m_device, Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Managed); GraphicsStream stream = m_vbTextured.Lock(0, 0, LockFlags.None); foreach (VertexLookup lookup in texturedVertexTable) { VertexInfo vertex = m_simpleMesh.VertexInfo[(int)lookup.VertexId]; stream.Write(new CustomVertex.PositionNormalTextured(vertex.X, vertex.Y, vertex.Z, vertex.NX, vertex.NY, vertex.NZ, vertex.CUVData[lookup.UVIndex].U, vertex.CUVData[lookup.UVIndex].V)); } m_vbTextured.Unlock(); m_ibTextured = new IndexBuffer(typeof(ushort), texturedIndexList.Count, m_device, Usage.WriteOnly, Pool.Managed); stream = m_ibTextured.Lock(0, 0, LockFlags.None); stream.Write(texturedIndexList.ToArray()); m_ibTextured.Unlock(); } m_vbTexturedLength = texturedVertexTable.Count; // color vb & ib if (coloredVertexTable.Count > 0) { m_vbColored = new VertexBuffer(typeof(CustomVertex.PositionNormalColored), coloredVertexTable.Count, m_device, Usage.WriteOnly, CustomVertex.PositionNormalColored.Format, Pool.Managed); GraphicsStream stream = m_vbColored.Lock(0, 0, LockFlags.None); foreach (VertexLookup lookup in coloredVertexTable) { VertexInfo vertex = m_simpleMesh.VertexInfo[(int)lookup.VertexId]; stream.Write(new CustomVertex.PositionNormalColored(vertex.X, vertex.Y, vertex.Z, vertex.NX, vertex.NY, vertex.NZ, lookup.Color.ToArgb())); } m_vbColored.Unlock(); m_ibColored = new IndexBuffer(typeof(ushort), coloredIndexList.Count, m_device, Usage.WriteOnly, Pool.Managed); stream = m_ibColored.Lock(0, 0, LockFlags.None); stream.Write(coloredIndexList.ToArray()); m_ibColored.Unlock(); } m_vbColoredLength = coloredVertexTable.Count; }
public void ReInitializeWithoutTexturing() { // prepare vars m_coloredTrifans.Clear(); m_texturedTrifans.Clear(); // loop through the texturing info and determine for each of them what // type of decoration it is. m_decorations = new MeshDecoration[0]; m_textures = new Texture[0]; // create a single trifan set of red trifans List <VertexLookup> coloredVertexTable = new List <VertexLookup>(); List <ushort> coloredIndexList = new List <ushort>(); for (int i = 0; i < (int)m_simpleMesh.SecondTrifanSet.TrifanCount; i++) { TrifanInfo trifan = m_simpleMesh.SecondTrifanSet.TrifanData[i]; Color color = Color.Red; TrifanDrawInfo trifanInfo = new TrifanDrawInfo(); trifanInfo.IndexBufferStart = (ushort)coloredIndexList.Count; trifanInfo.PrimitiveCount = trifan.VertexCount - 2; for (int j = 0; j < trifan.VertexIndices.Length; j++) { VertexLookup lookup = new VertexLookup(trifan.VertexIndices[j], 0, color); ushort vertexIndex; if (!coloredVertexTable.Contains(lookup)) { coloredVertexTable.Add(lookup); } vertexIndex = (ushort)coloredVertexTable.IndexOf(lookup); coloredIndexList.Add(vertexIndex); } m_coloredTrifans.Add(i, trifanInfo); } // now create the actual index & vertex buffers // texture vb & ib m_vbTexturedLength = 0; // color vb & ib if (coloredVertexTable.Count > 0) { m_vbColored = new VertexBuffer(typeof(CustomVertex.PositionNormalColored), coloredVertexTable.Count, m_device, Usage.WriteOnly, CustomVertex.PositionNormalColored.Format, Pool.Managed); GraphicsStream stream = m_vbColored.Lock(0, 0, LockFlags.None); foreach (VertexLookup lookup in coloredVertexTable) { VertexInfo vertex = m_simpleMesh.VertexInfo[(int)lookup.VertexId]; stream.Write(new CustomVertex.PositionNormalColored(vertex.X, vertex.Y, vertex.Z, vertex.NX, vertex.NY, vertex.NZ, lookup.Color.ToArgb())); } m_vbColored.Unlock(); m_ibColored = new IndexBuffer(typeof(ushort), coloredIndexList.Count, m_device, Usage.WriteOnly, Pool.Managed); stream = m_ibColored.Lock(0, 0, LockFlags.None); stream.Write(coloredIndexList.ToArray()); m_ibColored.Unlock(); } m_vbColoredLength = coloredVertexTable.Count; }