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())); }
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)); }
/// <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())); }
/// /// 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)); }
public CSG color(Color c) { CSG result = this.clone(); storage.set("material:color", $"{c.R} {c.G} {c.B}"); return(result); }
public CSG clone() { CSG csg = new CSG(); csg.setOptType(this.getOptType()); // sequential code // csg.polygons = new ArrayList<>(); // polygons.forEach((polygon) -> { // csg.polygons.add(polygon.clone()); // }); var selector = new Func <Polygon, Polygon>(p => p.clone()); if (polygons.Count > 200) { csg.polygons = polygons.AsParallel().Select(selector).ToList(); } else { csg.polygons = polygons.Select(selector).ToList(); } return(csg); }
/// <summary> /// Constructs a CSG from a list of <see cref="Polygon"/> instances. /// </summary> /// /// <param name="polygons">polygons</param> /// <returns>a CSG instance</returns> /// public static CSG fromPolygons(List <Polygon> polygons) { CSG csg = new CSG(); csg.polygons = polygons; return(csg); }
public static CSG hull(CSG csg, PropertyStorage storage) { List <IVector3d> points = new List <IVector3d>(csg.getPolygons().Count * 3); csg.getPolygons().ForEach(p => p.vertices.ForEach(v => points.Add(v.pos))); return(hull(points, storage)); }
/// <summary> /// Returns a csg consisting of the polygons of this csg and the specified csg. /// /// The purpose of this method is to allow fast union operations for objects that do not intersect. /// /// </summary> /// /// <p> /// <b>WARNING:</b> this method does not apply the csg algorithms. Therefore, please ensure that this csg and the /// specified csg do not intersect. /// /// <param name="csg">csg</param> /// /// <returns>a csg consisting of the polygons of this csg and the specified csg</returns> /// public CSG dumbUnion(CSG csg) { CSG result = this.clone(); CSG other = csg.clone(); result.polygons.AddRange(other.polygons); return(result); }
/// <summary> /// Returns this bounding box as csg. /// </summary> /// <returns>this bounding box as csg</returns> /// public CSG toCSG() { if (csg == null) { csg = cube.toCSG(); } return(csg); }
private CSG _differenceCSGBoundsOpt(CSG csg) { CSG b = csg; CSG a1 = this._differenceNoOpt(csg.getBounds().toCSG()); CSG a2 = this.intersect(csg.getBounds().toCSG()); return(a2._differenceNoOpt(b)._unionIntersectOpt(a1).optimization(getOptType())); }
/// <summary> /// Return a new CSG solid representing the union of this csg and the specified csgs. /// </summary> /// /// <b>Note:</b> Neither this csg nor the specified csg are weighted. /// /// <blockquote><pre> /// A.union(B) /// /// +-------+ +-------+ /// | | | | /// | A | | | /// | +--+----+ = | +----+ /// +----+--+ | +----+ | /// | B | | | /// | | | | /// +-------+ +-------+ /// </pre></blockquote> /// /// /// <param name="csgs">other csgs</param> /// /// <returns>union of this csg and the specified csgs</returns> /// public CSG union(List <CSG> csgs) { CSG result = this; foreach (CSG csg in csgs) { result = result.union(csg); } return(result); }
public static List <Polygon> boundaryPolygons(CSG csg) { List <Polygon> result = new List <Polygon>(); foreach (List <Polygon> polygonGroup in searchPlaneGroups(csg.getPolygons())) { result.AddRange(boundaryPolygonsOfPlaneGroup(polygonGroup)); } return(result); }
/// <summary> /// Saves the specified csg using STL ASCII format. /// </summary> /// <param name="path">destination path</param> /// <param name="csg">csg to save</param> /// <exception cref="IOException"></exception> /// public static void toStlFile(string p, CSG csg) { using (var file = File.Open(p, FileMode.Create | FileMode.Truncate)) { using (var writer = new StreamWriter(file, Encoding.UTF8)) { writer.Write("solid v3d.csg\n"); csg.getPolygons().ForEach(poly => writer.Write(poly.toStlString())); writer.Write("endsolid v3d.csg\n"); } } }
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> /// Return a new CSG solid representing the difference of this csg and the specified csg. /// </summary> /// /// <b>Note:</b> Neither this csg nor the specified csg are weighted. /// /// <code> /// A.difference(B) /// /// +-------+ +-------+ /// | | | | /// | A | | | /// | +--+----+ = | +--+ /// +----+--+ | +----+ /// | B | /// | | /// +-------+ /// </code> /// /// <param name="csg">other csg</param> /// <returns>difference of this csg and the specified csg</returns> /// public CSG difference(CSG csg) { switch (getOptType()) { case OptType.CSG_BOUND: return(_differenceCSGBoundsOpt(csg)); case OptType.POLYGON_BOUND: return(_differencePolygonBoundsOpt(csg)); default: return(_differenceNoOpt(csg)); } }
/// <summary> /// Constructs a CSG from a list of <see cref="Polygon"/> instances. /// </summary> /// /// <param name="storage">shared storage</param> /// <param name="polygons">polygons</param> /// <returns>a CSG instance</returns> /// public static CSG fromPolygons(PropertyStorage storage, List <Polygon> polygons) { CSG csg = new CSG(); csg.polygons = polygons; csg.storage = storage; foreach (Polygon polygon in polygons) { polygon.setStorage(storage); } return(csg); }
/// <summary> /// Return a new CSG solid representing the union of this csg and the specified csg. /// /// <b>Note:</b> Neither this csg nor the specified csg are weighted. /// /// <blockquote><pre> /// A.union(B) /// /// +-------+ +-------+ /// | | | | /// | A | | | /// | +--+----+ = | +----+ /// +----+--+ | +----+ | /// | B | | | /// | | | | /// +-------+ +-------+ /// </pre></blockquote> /// </summary> /// /// <param name="csg">other csg</param> /// /// <returns>union of this csg and the specified csg</returns> /// public CSG union(CSG csg) { switch (getOptType()) { case OptType.CSG_BOUND: return(_unionCSGBoundsOpt(csg)); case OptType.POLYGON_BOUND: return(_unionPolygonBoundsOpt(csg)); default: // return _unionIntersectOpt(csg); return(_unionNoOpt(csg)); } }
/// <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); }
/// <summary> /// Return a new CSG solid representing the intersection of this csg and the specified csgs. /// </summary> /// /// <b>Note:</b> Neither this csg nor the specified csgs are weighted. /// /// <code> /// A.intersect(B) /// /// +-------+ /// | | /// | A | /// | +--+----+ = +--+ /// +----+--+ | +--+ /// | B | /// | | /// +-------+ /// } /// </code> /// /// <param name="csgs">other csgs</param> /// <returns>intersection of this csg and the specified csgs</returns> /// public CSG intersect(List <CSG> csgs) { if (csgs.Count == 0) { return(this.clone()); } CSG csgsUnion = csgs[0]; for (int i = 1; i < csgs.Count; i++) { csgsUnion = csgsUnion.union(csgs[i]); } return(intersect(csgsUnion)); }
public List <Polygon> toPolygons() { CSG spherePrototype = new Sphere(getCornerRadius(), getResolution() * 2, getResolution()).toCSG(); double x = dimensions.x() / 2.0 - getCornerRadius(); double y = dimensions.y() / 2.0 - getCornerRadius(); double z = dimensions.z() / 2.0 - getCornerRadius(); CSG sphere1 = spherePrototype.transformed(Transform.unity().translate(-x, -y, -z)); CSG sphere2 = spherePrototype.transformed(Transform.unity().translate(x, -y, -z)); CSG sphere3 = spherePrototype.transformed(Transform.unity().translate(x, y, -z)); CSG sphere4 = spherePrototype.transformed(Transform.unity().translate(-x, y, -z)); CSG sphere5 = spherePrototype.transformed(Transform.unity().translate(-x, -y, z)); CSG sphere6 = spherePrototype.transformed(Transform.unity().translate(x, -y, z)); CSG sphere7 = spherePrototype.transformed(Transform.unity().translate(x, y, z)); CSG sphere8 = spherePrototype.transformed(Transform.unity().translate(-x, y, z)); List <Polygon> result = sphere1.union( sphere2, sphere3, sphere4, sphere5, sphere6, sphere7, sphere8).hull().getPolygons(); Transform locTransform = Transform.unity().translate(center); foreach (Polygon p in result) { p.transform(locTransform); } if (!centered) { Transform centerTransform = Transform.unity(). translate(dimensions.x() / 2.0, dimensions.y() / 2.0, dimensions.z() / 2.0); foreach (Polygon p in result) { p.transform(centerTransform); } } return(result); }
public double eval(IVector3d pos, CSG csg) { if (bounds == null) { this.bounds = csg.getBounds(); sPerUnit = (max - min) / (bounds.getMax().y() - bounds.getMin().y()); } double s = sPerUnit * (pos.y() - bounds.getMin().y()); if (centered) { s = s - (max - min) / 2.0; s = Math.Abs(s) * 2; } return(s); }
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> /// Returns the convex hull of this csg and the union of the specified csgs. /// </summary> /// /// <param name="csgs">csgs</param> /// <returns>the convex hull of this csg and the specified csgs</returns> /// public CSG hull(List <CSG> csgs) { CSG csgsUnion = new CSG(); csgsUnion.storage = storage; csgsUnion.optType = optType; csgsUnion.polygons = this.clone().polygons; csgs.ForEach(csg => { csgsUnion.polygons.AddRange(csg.clone().polygons); }); csgsUnion.polygons.ForEach(p => p.setStorage(storage)); return(csgsUnion.hull()); // CSG csgsUnion = this; // // for (CSG csg : csgs) { // csgsUnion = csgsUnion.union(csg); // } // // return csgsUnion.hull(); }
public double eval(IVector3d pos, CSG csg) { return(1.0); }
/// <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())); }
private CSG _unionCSGBoundsOpt(CSG csg) { Console.Error.WriteLine("WARNING: using " + OptType.NONE + " since other optimization types missing for union operation."); return(_unionIntersectOpt(csg)); }