Example #1
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));
        }
Example #2
0
        protected virtual DMesh3 BuildMesh_IdenticalWeld(STLSolid solid)
        {
            var builder = new DMesh3Builder();

            builder.AppendNewMesh(false, false, false, false);

            DVectorArray3f vertices = solid.Vertices;
            int            N        = vertices.Count;

            int[] mapV = new int[N];

            var uniqueV = new Dictionary <Vector3f, int>();

            for (int vi = 0; vi < N; ++vi)
            {
                Vector3f v = vertices[vi];
                int      existing_idx;
                if (uniqueV.TryGetValue(v, out existing_idx))
                {
                    mapV[vi] = existing_idx;
                }
                else
                {
                    int vid = builder.AppendVertex(v.x, v.y, v.z);
                    uniqueV[v] = vid;
                    mapV[vi]   = vid;
                }
            }

            append_mapped_triangles(solid, builder, mapV);
            return(builder.Meshes[0]);
        }
Example #3
0
        protected virtual void BuildMesh(STLSolid solid, IMeshBuilder builder)
        {
            if (RebuildStrategy == Strategy.AutoBestResult)
            {
                DMesh3 result = BuildMesh_Auto(solid);
                builder.AppendNewMesh(result);
            }
            else if (RebuildStrategy == Strategy.IdenticalVertexWeld)
            {
                DMesh3 result = BuildMesh_IdenticalWeld(solid);
                builder.AppendNewMesh(result);
            }
            else if (RebuildStrategy == Strategy.TolerantVertexWeld)
            {
                DMesh3 result = BuildMesh_TolerantWeld(solid, WeldTolerance);
                builder.AppendNewMesh(result);
            }
            else
            {
                BuildMesh_NoMerge(solid, builder);
            }

            if (WantPerTriAttribs && solid.TriAttribs != null && builder.SupportsMetaData)
            {
                builder.AppendMetaData(PerTriAttribMetadataName, solid.TriAttribs);
            }
        }
Example #4
0
        public void TestASCII()
        {
            STLSolid solid;

            using (var fileStream = File.Open("sample_stl.stl", FileMode.Open, FileAccess.Read))
            {
                solid = STLSolid.CreateFromASCIIStream(fileStream);
            }
            Assert.AreEqual(solid.Facets.Count, 8016);
        }
Example #5
0
 protected virtual void BuildMesh(STLSolid solid, IMeshBuilder builder)
 {
     if (RebuildStrategy == Strategy.IdenticalVertexWeld)
     {
         BuildMesh_IdenticalWeld(solid, builder);
     }
     else
     {
         BuildMesh_NoMerge(solid, builder);
     }
 }
Example #6
0
        void append_mapped_triangles(STLSolid solid, DMesh3Builder builder, int[] mapV)
        {
            int nTris = solid.Vertices.Count / 3;

            for (int ti = 0; ti < nTris; ++ti)
            {
                int a = mapV[3 * ti];
                int b = mapV[3 * ti + 1];
                int c = mapV[3 * ti + 2];
                if (a == b || a == c || b == c)     // don't try to add degenerate triangles
                {
                    continue;
                }
                builder.AppendTriangle(a, b, c);
            }
        }
Example #7
0
        protected virtual void BuildMesh_NoMerge(STLSolid solid, IMeshBuilder builder)
        {
            /*int meshID = */ builder.AppendNewMesh(false, false, false, false);

            DVectorArray3f vertices = solid.Vertices;
            int            nTris    = vertices.Count / 3;

            for (int ti = 0; ti < nTris; ++ti)
            {
                Vector3f va = vertices[3 * ti];
                int      a  = builder.AppendVertex(va.x, va.y, va.z);
                Vector3f vb = vertices[3 * ti + 1];
                int      b  = builder.AppendVertex(vb.x, vb.y, vb.z);
                Vector3f vc = vertices[3 * ti + 2];
                int      c  = builder.AppendVertex(vc.x, vc.y, vc.z);

                builder.AppendTriangle(a, b, c);
            }
        }
Example #8
0
        protected virtual void BuildMesh_IdenticalWeld(STLSolid solid, IMeshBuilder builder)
        {
            /*int meshID = */ builder.AppendNewMesh(false, false, false, false);

            DVectorArray3f vertices = solid.Vertices;
            int            N        = vertices.Count;

            int[] mapV = new int[N];

            Dictionary <Vector3f, int> uniqueV = new Dictionary <Vector3f, int>();

            for (int vi = 0; vi < N; ++vi)
            {
                Vector3f v = vertices[vi];
                int      existing_idx;
                if (uniqueV.TryGetValue(v, out existing_idx))
                {
                    mapV[vi] = existing_idx;
                }
                else
                {
                    int vid = builder.AppendVertex(v.x, v.y, v.z);
                    uniqueV[v] = vid;
                    mapV[vi]   = vid;
                }
            }


            int nTris = N / 3;

            for (int ti = 0; ti < nTris; ++ti)
            {
                int a = mapV[3 * ti];
                int b = mapV[3 * ti + 1];
                int c = mapV[3 * ti + 2];
                if (a == b || a == c || b == c)     // don't try to add degenerate triangles
                {
                    continue;
                }
                builder.AppendTriangle(a, b, c);
            }
        }
Example #9
0
        protected virtual DMesh3 BuildMesh_Auto(STLSolid solid)
        {
            DMesh3 fastWeldMesh = BuildMesh_IdenticalWeld(solid);
            int    fastWeldMesh_bdryCount;

            if (check_for_cracks(fastWeldMesh, out fastWeldMesh_bdryCount, WeldTolerance))
            {
                DMesh3 tolWeldMesh           = BuildMesh_TolerantWeld(solid, WeldTolerance);
                int    tolWeldMesh_bdryCount = count_boundary_edges(tolWeldMesh);

                if (tolWeldMesh_bdryCount < fastWeldMesh_bdryCount)
                {
                    return(tolWeldMesh);
                }
                else
                {
                    return(fastWeldMesh);
                }
            }

            return(fastWeldMesh);
        }
Example #10
0
 protected virtual void BuildMesh(STLSolid solid, IMeshBuilder builder)
 {
     if (RebuildStrategy == Strategy.AutoBestResult)
     {
         DMesh3 result = BuildMesh_Auto(solid);
         builder.AppendNewMesh(result);
     }
     else if (RebuildStrategy == Strategy.IdenticalVertexWeld)
     {
         DMesh3 result = BuildMesh_IdenticalWeld(solid);
         builder.AppendNewMesh(result);
     }
     else if (RebuildStrategy == Strategy.TolerantVertexWeld)
     {
         DMesh3 result = BuildMesh_TolerantWeld(solid, WeldTolerance);
         builder.AppendNewMesh(result);
     }
     else
     {
         BuildMesh_NoMerge(solid, builder);
     }
 }
Example #11
0
        protected virtual DMesh3 BuildMesh_TolerantWeld(STLSolid solid, double weld_tolerance)
        {
            var builder = new DMesh3Builder();

            builder.AppendNewMesh(false, false, false, false);

            DVectorArray3f vertices = solid.Vertices;
            int            N        = vertices.Count;

            int[] mapV = new int[N];


            AxisAlignedBox3d bounds = AxisAlignedBox3d.Empty;

            for (int i = 0; i < N; ++i)
            {
                bounds.Contain(vertices[i]);
            }

            // [RMS] because we are only searching within tiny radius, there is really no downside to
            // using lots of bins here, except memory usage. If we don't, and the mesh has a ton of triangles
            // very close together (happens all the time on big meshes!), then this step can start
            // to take an *extremely* long time!
            int num_bins = 256;

            if (N > 100000)
            {
                num_bins = 512;
            }

            if (N > 1000000)
            {
                num_bins = 1024;
            }

            if (N > 2000000)
            {
                num_bins = 2048;
            }

            if (N > 5000000)
            {
                num_bins = 4096;
            }

            var uniqueV = new PointHashGrid3d <int>(bounds.MaxDim / (float)num_bins, -1);
            var pos     = new Vector3f[N];

            for (int vi = 0; vi < N; ++vi)
            {
                Vector3f v = vertices[vi];

                var pair = uniqueV.FindNearestInRadius(v, weld_tolerance, (vid) =>
                {
                    return(v.Distance(pos[vid]));
                });
                if (pair.Key == -1)
                {
                    int vid = builder.AppendVertex(v.x, v.y, v.z);
                    uniqueV.InsertPoint(vid, v);
                    mapV[vi] = vid;
                    pos[vid] = v;
                }
                else
                {
                    mapV[vi] = pair.Key;
                }
            }

            append_mapped_triangles(solid, builder, mapV);
            return(builder.Meshes[0]);
        }
Example #12
0
        public IOReadResult Read(TextReader reader, ReadOptions options, IMeshBuilder builder)
        {
            if (options.CustomFlags != null)
            {
                ParseArguments(options.CustomFlags);
            }

            // format is just this, with facet repeated N times:
            //solid "stl_ascii"
            //  facet normal 0.722390830517 -0.572606861591 0.387650430202
            //    outer loop
            //      vertex 0.00659640412778 4.19127035141 -0.244179025292
            //      vertex -0.0458636470139 4.09951019287 -0.281960010529
            //      vertex 0.0286951716989 4.14693021774 -0.350856184959
            //    endloop
            //  endfacet
            //endsolid

            bool in_solid = false;

            //bool in_facet = false;
            //bool in_loop = false;
            //int vertices_in_loop = 0;

            Objects = new List <STLSolid>();

            int nLines = 0;

            while (reader.Peek() >= 0)
            {
                string line = reader.ReadLine();
                nLines++;
                string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    continue;
                }

                if (tokens[0].Equals("vertex", StringComparison.OrdinalIgnoreCase))
                {
                    float x = (tokens.Length > 1) ? Single.Parse(tokens[1]) : 0;
                    float y = (tokens.Length > 2) ? Single.Parse(tokens[2]) : 0;
                    float z = (tokens.Length > 3) ? Single.Parse(tokens[3]) : 0;
                    append_vertex(x, y, z);

                    // [RMS] we don't really care about these lines...
                    //} else if (tokens[0].Equals("outer", StringComparison.OrdinalIgnoreCase)) {
                    //    in_loop = true;
                    //    vertices_in_loop = 0;

                    //} else if (tokens[0].Equals("endloop", StringComparison.OrdinalIgnoreCase)) {
                    //    in_loop = false;
                }
                else if (tokens[0].Equals("facet", StringComparison.OrdinalIgnoreCase))
                {
                    if (in_solid == false)
                    {                          // handle bad STL
                        Objects.Add(new STLSolid()
                        {
                            Name = "unknown_solid"
                        });
                        in_solid = true;
                    }
                    //in_facet = true;
                    // ignore facet normal

                    // [RMS] also don't really need to do anything for this one
                    //} else if (tokens[0].Equals("endfacet", StringComparison.OrdinalIgnoreCase)) {
                    //in_facet = false;
                }
                else if (tokens[0].Equals("solid", StringComparison.OrdinalIgnoreCase))
                {
                    var newObj = new STLSolid();
                    if (tokens.Length == 2)
                    {
                        newObj.Name = tokens[1];
                    }
                    else
                    {
                        newObj.Name = "object_" + Objects.Count;
                    }

                    Objects.Add(newObj);
                    in_solid = true;
                }
                else if (tokens[0].Equals("endsolid", StringComparison.OrdinalIgnoreCase))
                {
                    // do nothing, done object
                    in_solid = false;
                }
            }

            foreach (STLSolid solid in Objects)
            {
                BuildMesh(solid, builder);
            }

            return(new IOReadResult(IOCode.Ok, ""));
        }