private CSG _differencePolygonBoundsOpt(CSG csg) { List <Polygon> inner = new List <Polygon>(); List <Polygon> outer = new List <Polygon>(); Bounds bounds = csg.getBounds(); this.polygons.ForEach(p => { if (bounds.intersects(p.getBounds())) { inner.Add(p); } else { outer.Add(p); } }); CSG innerCSG = CSG.fromPolygons(inner); List <Polygon> allPolygons = new List <Polygon>(); allPolygons.AddRange(outer); allPolygons.AddRange(innerCSG._differenceNoOpt(csg).polygons); return(CSG.fromPolygons(allPolygons).optimization(getOptType())); }
/// <summary> /// Optimizes for intersection. If csgs do not intersect create a new csg that consists of the polygon lists of this /// csg and the specified csg. In this case no further space partitioning is performed. /// </summary> /// /// <param name="csg">csg</param> /// <returns>the union of this csg and the specified csg</returns> /// private CSG _unionIntersectOpt(CSG csg) { bool intersects = false; Bounds bounds = csg.getBounds(); foreach (Polygon p in polygons) { if (bounds.intersects(p.getBounds())) { intersects = true; break; } } List <Polygon> allPolygons = new List <Polygon>(); if (intersects) { return(_unionNoOpt(csg)); } else { allPolygons.AddRange(this.polygons); allPolygons.AddRange(csg.polygons); } return(CSG.fromPolygons(allPolygons).optimization(getOptType())); }
public static CSG hull(List <IVector3d> points, PropertyStorage storage) { Point3d[] hullPoints = points.Select(vec => new Point3d(vec.x(), vec.y(), vec.z())).ToArray(); Hull hull = new Hull(); hull.Build(hullPoints); hull.Triangulate(); int[][] faces = hull.GetFaces(); List <Polygon> polygons = new List <Polygon>(); List <IVector3d> vertices = new List <IVector3d>(); foreach (int[] verts in faces) { foreach (int i in verts) { vertices.Add(points[hull.GetVertexPointIndices()[i]]); } polygons.Add(Polygon.fromPoints(vertices, storage)); vertices.Clear(); } return(CSG.fromPolygons(polygons)); }
/// /// Loads a CSG from stl. /// /// <param name="path">file path</param> /// <returns>CSG</returns> /// @throws IOException if loading failed /// public static CSG file(string path) { var solid = STLSolid.CreateFromFile(path); List <Polygon> polygons = new List <Polygon>(); List <IVector3d> vertices = new List <IVector3d>(); foreach (var facet in solid.Facets) { vertices.Add(Vector3d.xyz(facet.OuterLoop.V0.X, facet.OuterLoop.V0.Y, facet.OuterLoop.V0.Z)); vertices.Add(Vector3d.xyz(facet.OuterLoop.V1.X, facet.OuterLoop.V1.Y, facet.OuterLoop.V1.Z)); vertices.Add(Vector3d.xyz(facet.OuterLoop.V2.X, facet.OuterLoop.V2.Y, facet.OuterLoop.V2.Z)); if (vertices.Count == 3) { polygons.Add(Polygon.fromPoints(vertices)); vertices = new List <IVector3d>(); } } //foreach (IVector3d p in loader.parse(path)) //{ // vertices.Add(p.clone()); // if (vertices.Count == 3) // { // polygons.Add(Polygon.fromPoints(vertices)); // vertices = new List<IVector3d>(); // } //} return(CSG.fromPolygons(new PropertyStorage(), polygons)); }
private CSG _unionNoOpt(CSG csg) { Node a = new Node(this.clone().polygons); Node b = new Node(csg.clone().polygons); a.clipTo(b); b.clipTo(a); b.invert(); b.clipTo(a); b.invert(); a.build(b.allPolygons()); return(CSG.fromPolygons(a.allPolygons()).optimization(getOptType())); }
/// <summary> /// Returns a transformed copy of this CSG. /// </summary> /// /// <param name="transform">the transform to apply</param> /// /// <returns>a transformed copy of this CSG</returns> /// public CSG transformed(CSharpVecMath.Transform transform) { if (polygons.Count == 0) { return(clone()); } List <Polygon> newpolygons = this.polygons.Select( p => p.transformed(transform)).ToList(); CSG result = CSG.fromPolygons(newpolygons).optimization(getOptType()); result.storage = storage; return(result); }
private static CSG extrude(IVector3d dir, Polygon polygon1) { List <Polygon> newPolygons = new List <Polygon>(); if (dir.z() < 0) { throw new ArgumentException("z < 0 currently not supported for extrude: " + dir); } newPolygons.AddRange(PolygonUtil.concaveToConvex(polygon1)); Polygon polygon2 = polygon1.translated(dir); int numvertices = polygon1.vertices.Count; for (int i = 0; i < numvertices; i++) { int nexti = (i + 1) % numvertices; IVector3d bottomV1 = polygon1.vertices[i].pos; IVector3d topV1 = polygon2.vertices[i].pos; IVector3d bottomV2 = polygon1.vertices[nexti].pos; IVector3d topV2 = polygon2.vertices[nexti].pos; List <IVector3d> pPoints = new List <IVector3d> { bottomV2, topV2, topV1, bottomV1 }; newPolygons.Add(Polygon.fromPoints(pPoints, polygon1.getStorage())); } polygon2 = polygon2.flipped(); List <Polygon> topPolygons = PolygonUtil.concaveToConvex(polygon2); newPolygons.AddRange(topPolygons); return(CSG.fromPolygons(newPolygons)); }
/// <summary> /// Combines two polygons into one CSG object. Polygons p1 and p2 are treated as top and /// bottom of a tube segment with p1 and p2 as the profile. <b>Note:</b> both polygons must have the /// same number of vertices. This method does not guarantee intersection-free CSGs. It is in the /// responsibility of the caller to ensure that the orientation of p1 and p2 allow for /// intersection-free combination of both. /// </summary> /// <param name="p1">first polygon</param> /// <param name="p2">second polygon</param> /// <returns>List of polygons</returns> /// public static CSG combine(Polygon p1, Polygon p2) { return(CSG.fromPolygons(combine(p1, p2, true, true))); }
/// <summary> /// Returns this primitive as <see cref="CSG"/>. /// </summary> /// <returns>this primitive as <see cref="CSG"/></returns> /// public static CSG toCSG(this IPrimitive primitive) { return(CSG.fromPolygons(primitive.getProperties(), primitive.toPolygons())); }