Exemple #1
0
        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));
        }
Exemple #2
0
        /// <summary>
        /// Returns a triangulated version of this polygon.
        /// </summary>
        /// <returns>triangles</returns>
        ///
        public List <Polygon> toTriangles()
        {
            List <Polygon> result = new List <Polygon>();

            if (this.vertices.Count >= 3)
            {
                // TODO: improve the triangulation?
                //
                // If our polygon has more vertices, create
                // multiple triangles:
                Vertex firstVertexStl = this.vertices[0];
                for (int i = 0; i < this.vertices.Count - 2; i++)
                {
                    // create triangle
                    Polygon polygon = Polygon.fromPoints(
                        firstVertexStl.pos,
                        this.vertices[i + 1].pos,
                        this.vertices[i + 2].pos
                        );

                    result.Add(polygon);
                }
            }

            return(result);
        }
Exemple #3
0
        ///
        /// 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));
        }
Exemple #4
0
        public List <Polygon> toPolygons()
        {
            Func <int, IVector3d>      indexToPoint = i => points[i].clone();
            Func <List <int>, Polygon> faceListToPolygon
                = faceList => Polygon.fromPoints(faceList.Select(indexToPoint).ToList(), properties);

            return(faces.Select(faceListToPolygon).ToList());
        }
Exemple #5
0
        static List <IVector3d> toCW(List <IVector3d> points)
        {
            List <IVector3d> result = new List <IVector3d>(points);

            if (isCCW(Polygon.fromPoints(result)))
            {
                result.Reverse();
            }

            return(result);
        }
Exemple #6
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>
        /// <param name="bottom">defines whether to close the bottom of the tube</param>
        /// <param name="top">defines whether to close the top of the tube</param>
        /// <returns>List of polygons</returns>
        ///
        public static List <Polygon> combine(Polygon p1, Polygon p2, bool bottom, bool top)
        {
            List <Polygon> newPolygons = new List <Polygon>();

            if (p1.vertices.Count != p2.vertices.Count)
            {
                throw new Exception("Polygons must have the same number of vertices");
            }

            int numVertices = p1.vertices.Count;

            if (bottom)
            {
                newPolygons.Add(p1.flipped());
            }

            for (int i = 0; i < numVertices; i++)
            {
                int nexti = (i + 1) % numVertices;

                IVector3d bottomV1 = p1.vertices[i].pos;
                IVector3d topV1    = p2.vertices[i].pos;
                IVector3d bottomV2 = p1.vertices[nexti].pos;
                IVector3d topV2    = p2.vertices[nexti].pos;

                List <IVector3d> pPoints;

                pPoints = new List <IVector3d> {
                    bottomV2, topV2, topV1
                };
                newPolygons.Add(Polygon.fromPoints(pPoints, p1.getStorage()));
                pPoints = new List <IVector3d> {
                    bottomV2, topV1, bottomV1
                };
                newPolygons.Add(Polygon.fromPoints(pPoints, p1.getStorage()));
            }

            if (top)
            {
                newPolygons.Add(p2);
            }

            return(newPolygons);
        }
Exemple #7
0
        private static Polygon toPolygon(List <IVector3d> points, Plane plane)
        {
            //        List<Vector3d> points = edges.().Select(e => e.p1.pos).
            //                .ToList();
            Polygon p = Polygon.fromPoints(points);

            p.vertices.ForEach(vertex => vertex.normal = plane.normal.clone());

            // TODO Find out the meaning of foEachOrdered
            //p.vertices.forEachOrdered(vertex => {
            //    vertex.normal = plane.normal.clone();
            //});


            //        // we try to detect wrong orientation by comparing normals
            //        if (p.plane.normal.angle(plane.normal) > 0.1) {
            //            p.flip();
            //        }
            return(p);
        }
Exemple #8
0
        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));
        }
Exemple #9
0
 /// <summary>
 /// Extrudes the specified path (convex or concave polygon without holes or
 /// intersections, specified in CCW) into the specified direction.
 /// </summary>
 /// <param name="dir">direction</param>
 /// <param name="points">path (convex or concave polygon without holes or
 /// intersections)</param>
 ///
 /// <returns>a list containing the extruded polygon</returns>
 ///
 public static List <Polygon> points(IVector3d dir, bool top, bool bottom, params IVector3d[] points)
 {
     return(extrude(dir, Polygon.fromPoints(toCCW(points.ToList())), top, bottom));
 }
Exemple #10
0
        /// </summary>
        /// Extrudes the specified path (convex or concave polygon without holes or
        /// intersections, specified in CCW) into the specified direction.
        /// </summary>
        /// <param name="dir">direction</param>
        /// <param name="points">path (convex or concave polygon without holes or
        /// intersections)</param>
        ///
        /// <returns>a CSG object that consists of the extruded polygon</returns>
        ///
        public static CSG points(IVector3d dir, List <IVector3d> points)
        {
            List <IVector3d> newList = new List <IVector3d>(points);

            return(extrude(dir, Polygon.fromPoints(toCCW(newList))));
        }
Exemple #11
0
 /// <summary>
 /// Extrudes the specified path (convex or concave polygon without holes or
 /// intersections, specified in CCW) into the specified direction.
 /// </summary>
 /// <param name="dir">direction</param>
 /// <param name="points">path (convex or concave polygon without holes or
 /// intersections)</param>
 ///
 /// <returns>a CSG object that consists of the extruded polygon</returns>
 ///
 public static CSG points(IVector3d dir, params IVector3d[] points)
 {
     return(extrude(dir, Polygon.fromPoints(toCCW(points.ToList()))));
 }
Exemple #12
0
        private static List <Polygon> extrude(IVector3d dir, Polygon polygon1, bool top, bool bottom)
        {
            List <Polygon> newPolygons = new List <Polygon>();


            if (bottom)
            {
                newPolygons.AddRange(PolygonUtil.concaveToConvex(polygon1));
            }

            Polygon polygon2 = polygon1.translated(dir);

            Transform rot = Transform.unity();

            IVector3d a = polygon2.getPlane().getNormal().normalized();
            IVector3d b = dir.normalized();

            IVector3d c = a.crossed(b);

            double l = c.magnitude(); // sine of angle

            if (l > 1e-9)
            {
                IVector3d axis  = c.times(1.0 / l);
                double    angle = a.angle(b);

                double sx = 0;
                double sy = 0;
                double sz = 0;

                int n = polygon2.vertices.Count;

                foreach (Vertex v in polygon2.vertices)
                {
                    sx += v.pos.x();
                    sy += v.pos.y();
                    sz += v.pos.z();
                }

                IVector3d center = Vector3d.xyz(sx / n, sy / n, sz / n);

                rot = rot.rot(center, axis, angle * Math.PI / 180.0);

                foreach (Vertex v in polygon2.vertices)
                {
                    v.pos = rot.transform(v.pos);
                }
            }

            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);

            if (top)
            {
                newPolygons.AddRange(topPolygons);
            }

            return(newPolygons);
        }
Exemple #13
0
        /// <summary>
        /// Extrudes the specified path (convex or concave polygon without holes or
        /// intersections, specified in CCW) into the specified direction.
        /// </summary>
        /// <param name="dir">direction</param>
        /// <param name="points1">path (convex or concave polygon without holes or
        /// intersections)</param>
        /// <param name="points1">path (convex or concave polygon without holes or
        /// intersections)</param>
        ///
        /// <returns>a list containing the extruded polygon</returns>
        ///
        public static List <Polygon> points(IVector3d dir, bool top, bool bottom, List <IVector3d> points1)
        {
            List <IVector3d> newList1 = new List <IVector3d>(points1);

            return(extrude(dir, Polygon.fromPoints(toCCW(newList1)), top, bottom));
        }
Exemple #14
0
        /// <summary>
        /// Returns a list of all boundary paths.
        /// </summary>
        /// <param name="boundaryEdges">boundary edges (all paths must be closed)</param>
        /// <returns></returns>
        private static List <Polygon> boundaryPaths(List <Edge> boundaryEdges)
        {
            List <Polygon> result = new List <Polygon>();

            bool[] used       = new bool[boundaryEdges.Count];
            int    startIndex = 0;
            Edge   edge       = boundaryEdges[startIndex];

            used[startIndex] = true;

            startIndex = 1;

            while (startIndex > 0)
            {
                List <IVector3d> boundaryPath = new List <IVector3d>();

                while (true)
                {
                    Edge finalEdge = edge;

                    boundaryPath.Add(finalEdge.p1.pos);

                    Console.Out.Write("edge: " + edge.p2.pos);

                    Edge nextEdgeResult = boundaryEdges.
                                          Where(e => finalEdge.p2.Equals(e.p1)).First();

                    if (nextEdgeResult == null)
                    {
                        Console.Out.WriteLine("ERROR: unclosed path:"
                                              + " no edge found with " + finalEdge.p2);
                        break;
                    }

                    Edge nextEdge = nextEdgeResult;

                    int nextEdgeIndex = boundaryEdges.IndexOf(nextEdge);

                    if (used[nextEdgeIndex])
                    {
                        break;
                    }

                    edge = nextEdge;
                    Console.Out.WriteLine("=> edge: " + edge.p1.pos);
                    used[nextEdgeIndex] = true;
                }

                if (boundaryPath.Count < 3)
                {
                    break;
                }

                result.Add(Polygon.fromPoints(boundaryPath));
                startIndex = nextUnused(used);

                if (startIndex > 0)
                {
                    edge             = boundaryEdges[startIndex];
                    used[startIndex] = true;
                }
            }

            Console.Out.WriteLine("paths: " + result.Count);

            return(result);
        }