bool compute_outer_wall()
        {
            SocketMesh       = new DMesh3(InnerMesh);
            LastInnerGroupID = SocketMesh.AllocateTriangleGroup();
            FaceGroupUtil.SetGroupID(SocketMesh, LastInnerGroupID);

            if (DebugStep <= 1)
            {
                return(true);
            }

            double          use_thickness = thickness;
            MeshExtrudeMesh extrude       = new MeshExtrudeMesh(SocketMesh);

            extrude.ExtrudedPositionF = (v, n, vid) => {
                return(v + use_thickness * (Vector3d)n);
            };
            if (extrude.Extrude() == false)
            {
                return(false);
            }

            LastExtrudeOuterGroupID = extrude.OffsetGroupID;
            LastStitchGroupID       = extrude.StitchGroupIDs[0];

            return(true);
        }
		List<DMesh3> process_solids(List<DMesh3> solid_components)
		{
			// [TODO] maybe we can have special tags that extract out certain meshes?

			var combinedSolid = new DMesh3(SourceMesh.Components | MeshComponents.FaceGroups);
			var editor = new MeshEditor(combinedSolid);
			foreach (DMesh3 solid in solid_components)
			{
				editor.AppendMesh(solid, combinedSolid.AllocateTriangleGroup());
			}

			return new List<DMesh3>() { combinedSolid };
		}
Exemple #3
0
        public AppendInfo AppendConnectorTo(DMesh3 mesh, Vector3d translate)
        {
            validate_geometry();

            AppendInfo info = new AppendInfo();

            MeshEditor editor = new MeshEditor(mesh);

            int[] mapV;

            if (HasInner)
            {
                info.InnerGID = mesh.AllocateTriangleGroup();
                editor.AppendMesh(InnerMesh, out mapV, info.InnerGID);
                info.InnerLoop = EdgeLoop.FromVertices(mesh, new MappedList(InnerLoop.Vertices, mapV));

                MeshTransforms.PerVertexTransform(mesh, InnerMesh.VertexIndices(),
                                                  (vid) => { return(mapV[vid]); },
                                                  (v, old_vid, new_vid) => { return(v + translate); });
            }
            else
            {
                info.InnerGID  = -1;
                info.InnerLoop = null;
            }

            info.OuterGID = mesh.AllocateTriangleGroup();
            editor.AppendMesh(OuterMesh, out mapV, info.OuterGID);
            info.OuterLoop = EdgeLoop.FromVertices(mesh, new MappedList(OuterLoop.Vertices, mapV));

            MeshTransforms.PerVertexTransform(mesh, OuterMesh.VertexIndices(),
                                              (vid) => { return(mapV[vid]); },
                                              (v, old_vid, new_vid) => { return(v + translate); });

            return(info);
        }
Exemple #4
0
        public bool Apply()
        {
            // do a simple fill
            SimpleHoleFiller simplefill = new SimpleHoleFiller(Mesh, FillLoop);
            int  fill_gid = Mesh.AllocateTriangleGroup();
            bool bOK      = simplefill.Fill(fill_gid);

            if (bOK == false)
            {
                return(false);
            }

            if (FillLoop.Vertices.Length <= 3)
            {
                FillTriangles = simplefill.NewTriangles;
                FillVertices  = new int[0];
                return(true);
            }

            // extract the simple fill mesh as a submesh, via RegionOperator, so we can backsub later
            HashSet <int> intial_fill_tris = new HashSet <int>(simplefill.NewTriangles);

            regionop = new RegionOperator(Mesh, simplefill.NewTriangles,
                                          (submesh) => { submesh.ComputeTriMaps = true; });
            fillmesh = regionop.Region.SubMesh;

            // for each boundary vertex, compute the exterior angle sum
            // we will use this to compute gaussian curvature later
            boundaryv           = new HashSet <int>(MeshIterators.BoundaryEdgeVertices(fillmesh));
            exterior_angle_sums = new Dictionary <int, double>();
            if (IgnoreBoundaryTriangles == false)
            {
                foreach (int sub_vid in boundaryv)
                {
                    double angle_sum = 0;
                    int    base_vid  = regionop.Region.MapVertexToBaseMesh(sub_vid);
                    foreach (int tid in regionop.BaseMesh.VtxTrianglesItr(base_vid))
                    {
                        if (intial_fill_tris.Contains(tid) == false)
                        {
                            Index3i et  = regionop.BaseMesh.GetTriangle(tid);
                            int     idx = IndexUtil.find_tri_index(base_vid, ref et);
                            angle_sum += regionop.BaseMesh.GetTriInternalAngleR(tid, idx);
                        }
                    }
                    exterior_angle_sums[sub_vid] = angle_sum;
                }
            }


            // try to guess a reasonable edge length that will give us enough geometry to work with in simplify pass
            double loop_mine, loop_maxe, loop_avge, fill_mine, fill_maxe, fill_avge;

            MeshQueries.EdgeLengthStatsFromEdges(Mesh, FillLoop.Edges, out loop_mine, out loop_maxe, out loop_avge);
            MeshQueries.EdgeLengthStats(fillmesh, out fill_mine, out fill_maxe, out fill_avge);
            double remesh_target_len = loop_avge;

            if (fill_maxe / remesh_target_len > 10)
            {
                remesh_target_len = fill_maxe / 10;
            }
            //double remesh_target_len = Math.Min(loop_avge, fill_avge / 4);

            // remesh up to target edge length, ideally gives us some triangles to work with
            RemesherPro remesh1 = new RemesherPro(fillmesh);

            remesh1.SmoothSpeedT = 1.0;
            MeshConstraintUtil.FixAllBoundaryEdges(remesh1);
            //remesh1.SetTargetEdgeLength(remesh_target_len / 2);       // would this speed things up? on large regions?
            //remesh1.FastestRemesh();
            remesh1.SetTargetEdgeLength(remesh_target_len);
            remesh1.FastestRemesh();

            /*
             * first round: collapse to minimal mesh, while flipping to try to
             * get to ballpark minimal mesh. We stop these passes as soon as
             * we have done two rounds where we couldn't do another collapse
             *
             * This is the most unstable part of the algorithm because there
             * are strong ordering effects. maybe we could sort the edges somehow??
             */

            int zero_collapse_passes = 0;
            int collapse_passes      = 0;

            while (collapse_passes++ < 20 && zero_collapse_passes < 2)
            {
                // collapse pass
                int NE        = fillmesh.MaxEdgeID;
                int collapses = 0;
                for (int ei = 0; ei < NE; ++ei)
                {
                    if (fillmesh.IsEdge(ei) == false || fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }
                    Index2i ev = fillmesh.GetEdgeV(ei);
                    bool    a_bdry = boundaryv.Contains(ev.a), b_bdry = boundaryv.Contains(ev.b);
                    if (a_bdry && b_bdry)
                    {
                        continue;
                    }
                    int      keepv  = (a_bdry) ? ev.a : ev.b;
                    int      otherv = (keepv == ev.a) ? ev.b : ev.a;
                    Vector3d newv   = fillmesh.GetVertex(keepv);
                    if (MeshUtil.CheckIfCollapseCreatesFlip(fillmesh, ei, newv))
                    {
                        continue;
                    }
                    DMesh3.EdgeCollapseInfo info;
                    MeshResult result = fillmesh.CollapseEdge(keepv, otherv, out info);
                    if (result == MeshResult.Ok)
                    {
                        collapses++;
                    }
                }
                if (collapses == 0)
                {
                    zero_collapse_passes++;
                }
                else
                {
                    zero_collapse_passes = 0;
                }

                // flip pass. we flip in these cases:
                //  1) if angle between current triangles is too small (slightly more than 90 degrees, currently)
                //  2) if angle between flipped triangles is smaller than between current triangles
                //  3) if flipped edge length is shorter *and* such a flip won't flip the normal
                NE = fillmesh.MaxEdgeID;
                Vector3d n1, n2, on1, on2;
                for (int ei = 0; ei < NE; ++ei)
                {
                    if (fillmesh.IsEdge(ei) == false || fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }
                    bool do_flip = false;

                    Index2i ev = fillmesh.GetEdgeV(ei);
                    MeshUtil.GetEdgeFlipNormals(fillmesh, ei, out n1, out n2, out on1, out on2);
                    double dot_cur  = n1.Dot(n2);
                    double dot_flip = on1.Dot(on2);
                    if (n1.Dot(n2) < 0.1 || dot_flip > dot_cur + MathUtil.Epsilonf)
                    {
                        do_flip = true;
                    }

                    if (do_flip == false)
                    {
                        Index2i otherv   = fillmesh.GetEdgeOpposingV(ei);
                        double  len_e    = fillmesh.GetVertex(ev.a).Distance(fillmesh.GetVertex(ev.b));
                        double  len_flip = fillmesh.GetVertex(otherv.a).Distance(fillmesh.GetVertex(otherv.b));
                        if (len_flip < len_e)
                        {
                            if (MeshUtil.CheckIfEdgeFlipCreatesFlip(fillmesh, ei) == false)
                            {
                                do_flip = true;
                            }
                        }
                    }

                    if (do_flip)
                    {
                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                    }
                }
            }

            // Sometimes, for some reason, we have a remaining interior vertex (have only ever seen one?)
            // Try to force removal of such vertices, even if it makes ugly mesh
            remove_remaining_interior_verts();


            // enable/disable passes.
            bool DO_FLATTER_PASS   = true;
            bool DO_CURVATURE_PASS = OptimizeDevelopability && true;
            bool DO_AREA_PASS      = OptimizeDevelopability && OptimizeTriangles && true;


            /*
             * In this pass we repeat the flipping iterations from the previous pass.
             *
             * Note that because of the always-flip-if-dot-is-small case (commented),
             * this pass will frequently not converge, as some number of edges will
             * be able to flip back and forth (because neither has large enough dot).
             * This is not ideal, but also, if we remove this behavior, then we
             * generally get worse fills. This case basically introduces a sort of
             * randomization factor that lets us escape local minima...
             *
             */

            HashSet <int> remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
            HashSet <int> updated_edges   = new HashSet <int>();

            int flatter_passes    = 0;
            int zero_flips_passes = 0;

            while (flatter_passes++ < 40 && zero_flips_passes < 2 && remaining_edges.Count() > 0 && DO_FLATTER_PASS)
            {
                zero_flips_passes++;
                foreach (int ei in remaining_edges)
                {
                    if (fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }

                    bool do_flip = false;

                    Index2i  ev = fillmesh.GetEdgeV(ei);
                    Vector3d n1, n2, on1, on2;
                    MeshUtil.GetEdgeFlipNormals(fillmesh, ei, out n1, out n2, out on1, out on2);
                    double dot_cur  = n1.Dot(n2);
                    double dot_flip = on1.Dot(on2);
                    if (flatter_passes < 20 && dot_cur < 0.1)   // this check causes oscillatory behavior
                    {
                        do_flip = true;
                    }
                    if (dot_flip > dot_cur + MathUtil.Epsilonf)
                    {
                        do_flip = true;
                    }

                    if (do_flip)
                    {
                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result == MeshResult.Ok)
                        {
                            zero_flips_passes = 0;
                            add_all_edges(ei, updated_edges);
                        }
                    }
                }

                var tmp = remaining_edges;
                remaining_edges = updated_edges;
                updated_edges   = tmp; updated_edges.Clear();
            }


            int curvature_passes = 0;

            if (DO_CURVATURE_PASS)
            {
                curvatures = new double[fillmesh.MaxVertexID];
                foreach (int vid in fillmesh.VertexIndices())
                {
                    update_curvature(vid);
                }

                remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
                updated_edges   = new HashSet <int>();

                /*
                 *  In this pass we try to minimize gaussian curvature at all the vertices.
                 *  This will recover sharp edges, etc, and do lots of good stuff.
                 *  However, this pass will not make much progress if we are not already
                 *  relatively close to a minimal mesh, so it really relies on the previous
                 *  passes getting us in the ballpark.
                 */
                while (curvature_passes++ < 40 && remaining_edges.Count() > 0 && DO_CURVATURE_PASS)
                {
                    foreach (int ei in remaining_edges)
                    {
                        if (fillmesh.IsBoundaryEdge(ei))
                        {
                            continue;
                        }

                        Index2i ev = fillmesh.GetEdgeV(ei);
                        Index2i ov = fillmesh.GetEdgeOpposingV(ei);

                        int find_other = fillmesh.FindEdge(ov.a, ov.b);
                        if (find_other != DMesh3.InvalidID)
                        {
                            continue;
                        }

                        double total_curv_cur = curvature_metric_cached(ev.a, ev.b, ov.a, ov.b);
                        if (total_curv_cur < MathUtil.ZeroTolerancef)
                        {
                            continue;
                        }

                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result != MeshResult.Ok)
                        {
                            continue;
                        }

                        double total_curv_flip = curvature_metric_eval(ev.a, ev.b, ov.a, ov.b);

                        bool keep_flip = total_curv_flip < total_curv_cur - MathUtil.ZeroTolerancef;
                        if (keep_flip == false)
                        {
                            result = fillmesh.FlipEdge(ei, out info);
                        }
                        else
                        {
                            update_curvature(ev.a); update_curvature(ev.b);
                            update_curvature(ov.a); update_curvature(ov.b);
                            add_all_edges(ei, updated_edges);
                        }
                    }
                    var tmp = remaining_edges;
                    remaining_edges = updated_edges;
                    updated_edges   = tmp; updated_edges.Clear();
                }
            }
            //System.Console.WriteLine("collapse {0}   flatter {1}   curvature {2}", collapse_passes, flatter_passes, curvature_passes);

            /*
             * In this final pass, we try to improve triangle quality. We flip if
             * the flipped triangles have better total aspect ratio, and the
             * curvature doesn't change **too** much. The .DevelopabilityTolerance
             * parameter determines what is "too much" curvature change.
             */
            if (DO_AREA_PASS)
            {
                remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
                updated_edges   = new HashSet <int>();
                int area_passes = 0;
                while (remaining_edges.Count() > 0 && area_passes < 20)
                {
                    area_passes++;
                    foreach (int ei in remaining_edges)
                    {
                        if (fillmesh.IsBoundaryEdge(ei))
                        {
                            continue;
                        }

                        Index2i ev = fillmesh.GetEdgeV(ei);
                        Index2i ov = fillmesh.GetEdgeOpposingV(ei);

                        int find_other = fillmesh.FindEdge(ov.a, ov.b);
                        if (find_other != DMesh3.InvalidID)
                        {
                            continue;
                        }

                        double total_curv_cur = curvature_metric_cached(ev.a, ev.b, ov.a, ov.b);

                        double a = aspect_metric(ei);
                        if (a > 1)
                        {
                            continue;
                        }

                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result != MeshResult.Ok)
                        {
                            continue;
                        }

                        double total_curv_flip = curvature_metric_eval(ev.a, ev.b, ov.a, ov.b);

                        bool keep_flip = Math.Abs(total_curv_cur - total_curv_flip) < DevelopabilityTolerance;
                        if (keep_flip == false)
                        {
                            result = fillmesh.FlipEdge(ei, out info);
                        }
                        else
                        {
                            update_curvature(ev.a); update_curvature(ev.b);
                            update_curvature(ov.a); update_curvature(ov.b);
                            add_all_edges(ei, updated_edges);
                        }
                    }
                    var tmp = remaining_edges;
                    remaining_edges = updated_edges;
                    updated_edges   = tmp; updated_edges.Clear();
                }
            }


            regionop.BackPropropagate();
            FillTriangles = regionop.CurrentBaseTriangles;
            FillVertices  = regionop.CurrentBaseInteriorVertices().ToArray();

            return(true);
        }
Exemple #5
0
  public void takePointsinandAddtoMesh(List <Vector3d> pointers)
  {
      List <int>      tris    = new List <int>();
      List <Vector3d> normals = new List <Vector3d>();
      float           normal  = .01f;



      if (currentMesh == null)
      {
//ok so first mesh is not been created yet so create it from the first frame
          int counter = 0;
          foreach (Vector3d line in pointers)
          {
              counter++;
//Debug.Log(line);
              tris.Add(counter);
              tris.Add(counter);
              tris.Add(counter);

              normals.Add(new Vector3d(normal, normal, normal));
          }

          DMesh3         pointSet = DMesh3Builder.Build(pointers, tris, normals);
          PointAABBTree3 bvtree   = new PointAABBTree3(pointSet, true);
          bvtree.FastWindingNumber(Vector3d.Zero);
// estimate point area based on nearest-neighbour distance
          double[] areas = new double[pointSet.MaxVertexID];
          foreach (int vid in pointSet.VertexIndices())
          {
              bvtree.PointFilterF = (i) => { return(i != vid); }; // otherwise vid is nearest to vid!
              int    near_vid = bvtree.FindNearestPoint(pointSet.GetVertex(vid));
              double dist     = pointSet.GetVertex(vid).Distance(pointSet.GetVertex(near_vid));
              areas[vid] = Circle2d.RadiusArea(dist);
          }
          bvtree.FWNAreaEstimateF = (vid) => {
              return(areas[vid]);
          };
          MarchingCubes mc = new MarchingCubes();
          mc.Implicit = new PWNImplicit()
          {
              Spatial = bvtree
          };
          mc.IsoValue = 0.0;
          mc.CubeSize = bvtree.Bounds.MaxDim / 10;
          mc.Bounds   = bvtree.Bounds.Expanded(mc.CubeSize * 3);
          mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
          mc.Generate();
          DMesh3 resultMesh = mc.Mesh;
          //  g3UnityUtils.SetGOMesh(transform.gameObject, resultMesh);
          currentMesh = resultMesh;
      }
      else
      {
//ok so this is where we are proscessing second mesh
          int counter = 0;
          foreach (Vector3d line in pointers)
          {
              counter++;
//Debug.Log(line);
              tris.Add(counter);
              tris.Add(counter);
              tris.Add(counter);

              normals.Add(new Vector3d(normal, normal, normal));
          }

          DMesh3         pointSet = DMesh3Builder.Build(pointers, tris, normals);
          PointAABBTree3 bvtree   = new PointAABBTree3(pointSet, true);
          bvtree.FastWindingNumber(Vector3d.Zero);
// estimate point area based on nearest-neighbour distance
          double[] areas = new double[pointSet.MaxVertexID];
          foreach (int vid in pointSet.VertexIndices())
          {
              bvtree.PointFilterF = (i) => { return(i != vid); }; // otherwise vid is nearest to vid!
              int    near_vid = bvtree.FindNearestPoint(pointSet.GetVertex(vid));
              double dist     = pointSet.GetVertex(vid).Distance(pointSet.GetVertex(near_vid));
              areas[vid] = Circle2d.RadiusArea(dist);
          }
          bvtree.FWNAreaEstimateF = (vid) => {
              return(areas[vid]);
          };
          MarchingCubes mc = new MarchingCubes();
          mc.Implicit = new PWNImplicit()
          {
              Spatial = bvtree
          };
          mc.IsoValue = 0.0;
          mc.CubeSize = bvtree.Bounds.MaxDim / 10;
          mc.Bounds   = bvtree.Bounds.Expanded(mc.CubeSize * 3);
          mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
          mc.Generate();
          DMesh3     resultMesh = mc.Mesh;
          MeshEditor editor     = new MeshEditor(currentMesh);

          editor.AppendMesh(resultMesh, currentMesh.AllocateTriangleGroup());
//suspected its crashing after mesh is over 64000 faces,
          faceLog.text = "Vertex Count =  " + transform.gameObject.GetComponent <MeshFilter>().mesh.triangles.Length;

          g3UnityUtils.SetGOMesh(transform.gameObject, currentMesh);
      }
  }
Exemple #6
0
  public void fpMeshPointsfromTextFileWithaSecondPoints()
  {
//this is used in the fast points winding scene to optimize algorithm and make sure its working well
//it reads points via text files and then meshes them
      List <Vector3d> points  = new List <Vector3d>();
      List <int>      tris    = new List <int>();
      List <Vector3d> normals = new List <Vector3d>();
      float           normal  = .01f;

      string toPull = ReadString();

      string[] linesInFile = toPull.Split('\n');

      int counter = 0;

      foreach (string line in linesInFile)
      {
          counter++;
//Debug.Log(line);

          if (!string.IsNullOrEmpty(line))
          {
              points.Add(StringToVector3(line));
              tris.Add(counter);
              tris.Add(counter);
              tris.Add(counter);

              normals.Add(new Vector3d(normal, normal, normal));
          }
      }

      DMesh3         pointSet = DMesh3Builder.Build(points, tris, normals);
      PointAABBTree3 bvtree   = new PointAABBTree3(pointSet, true);

      bvtree.FastWindingNumber(Vector3d.Zero);
// estimate point area based on nearest-neighbour distance
      double[] areas = new double[pointSet.MaxVertexID];
      foreach (int vid in pointSet.VertexIndices())
      {
          bvtree.PointFilterF = (i) => { return(i != vid); }; // otherwise vid is nearest to vid!
          int    near_vid = bvtree.FindNearestPoint(pointSet.GetVertex(vid));
          double dist     = pointSet.GetVertex(vid).Distance(pointSet.GetVertex(near_vid));
          areas[vid] = Circle2d.RadiusArea(dist);
      }
      bvtree.FWNAreaEstimateF = (vid) => {
          return(areas[vid]);
      };
      MarchingCubes mc = new MarchingCubes();

      mc.Implicit = new PWNImplicit()
      {
          Spatial = bvtree
      };
      mc.IsoValue = 0.0;
      mc.CubeSize = bvtree.Bounds.MaxDim / 50;
      mc.Bounds   = bvtree.Bounds.Expanded(mc.CubeSize * 3);
      mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
      mc.Generate();
      DMesh3 resultMesh = mc.Mesh;

      g3UnityUtils.SetGOMesh(transform.gameObject, resultMesh);

      /*  MarchingCubes mc = new MarchingCubes();
       *   mc.Implicit = new PWNImplicit() { Spatial =  bvtree };
       *   mc.IsoValue = 0.0;
       *   mc.CubeSize = bvtree.Bounds.MaxDim / 10;
       *   mc.Bounds =  bvtree.Bounds.Expanded(mc.CubeSize * 3);
       *   mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
       *   mc.Generate();
       *   DMesh3 resultMesh = mc.Mesh;
       *   g3UnityUtils.SetGOMesh(transform.gameObject, resultMesh);
       */
//ok now that we meshed the first point set, lets try to take in a second frame of points and then add to orginal dmesh
      points  = new List <Vector3d>();
      tris    = new List <int>();
      normals = new List <Vector3d>();


      toPull      = ReadString1();
      linesInFile = toPull.Split('\n');

      counter = 0;
      foreach (string line in linesInFile)
      {
          counter++;
          Debug.Log(line);

          if (!string.IsNullOrEmpty(line))
          {
              points.Add(StringToVector3(line));
              tris.Add(counter);
              tris.Add(counter);
              tris.Add(counter);

              normals.Add(new Vector3d(normal, normal, normal));
          }
      }
      pointSet = DMesh3Builder.Build(points, tris, normals);
      bvtree   = new PointAABBTree3(pointSet, true);
      bvtree.FastWindingNumber(Vector3d.Zero);
// estimate point area based on nearest-neighbour distance
      areas = new double[pointSet.MaxVertexID];
      foreach (int vid in pointSet.VertexIndices())
      {
          bvtree.PointFilterF = (i) => { return(i != vid); }; // otherwise vid is nearest to vid!
          int    near_vid = bvtree.FindNearestPoint(pointSet.GetVertex(vid));
          double dist     = pointSet.GetVertex(vid).Distance(pointSet.GetVertex(near_vid));
          areas[vid] = Circle2d.RadiusArea(dist);
      }
      bvtree.FWNAreaEstimateF = (vid) => {
          return(areas[vid]);
      };
      mc          = new MarchingCubes();
      mc.Implicit = new PWNImplicit()
      {
          Spatial = bvtree
      };
      mc.IsoValue = 0.0;
      mc.CubeSize = bvtree.Bounds.MaxDim / 50;
      mc.Bounds   = bvtree.Bounds.Expanded(mc.CubeSize * 3);
      mc.RootMode = MarchingCubes.RootfindingModes.Bisection;
      mc.Generate();
      DMesh3     resultMesh1 = mc.Mesh;
      MeshEditor editor      = new MeshEditor(resultMesh);

      editor.AppendMesh(resultMesh1, resultMesh.AllocateTriangleGroup());

      g3UnityUtils.SetGOMesh(transform.gameObject, resultMesh1);

      //  g3UnityUtils.SetGOMesh(transform.gameObject, resultMesh);
  }
Exemple #7
0
        List <Polygon2d> decompose_cluster_up(DMesh3 mesh)
        {
            optimize_mesh(mesh);
            mesh.CompactInPlace();
            mesh.DiscardTriangleGroups(); mesh.EnableTriangleGroups(0);

            double minLength = Settings.MaxBridgeWidthMM * 0.75;
            double minArea   = minLength * minLength;

            Dictionary <int, double>         areas   = new Dictionary <int, double>();
            Dictionary <int, HashSet <int> > trisets = new Dictionary <int, HashSet <int> >();
            HashSet <int> active_groups = new HashSet <int>();

            Action <int, int> add_tri_to_group = (tid, gid) => {
                mesh.SetTriangleGroup(tid, gid);
                areas[gid] = areas[gid] + mesh.GetTriArea(tid);
                trisets[gid].Add(tid);
            };
            Action <int, int> add_group_to_group = (gid, togid) => {
                var set = trisets[togid];
                foreach (int tid in trisets[gid])
                {
                    mesh.SetTriangleGroup(tid, togid);
                    set.Add(tid);
                }
                areas[togid] += areas[gid];
                active_groups.Remove(gid);
            };
            Func <IEnumerable <int>, int> find_min_area_group = (tri_itr) => {
                int min_gid = -1; double min_area = double.MaxValue;
                foreach (int tid in tri_itr)
                {
                    int    gid = mesh.GetTriangleGroup(tid);
                    double a   = areas[gid];
                    if (a < min_area)
                    {
                        min_area = a;
                        min_gid  = gid;
                    }
                }
                return(min_gid);
            };


            foreach (int eid in MeshIterators.InteriorEdges(mesh))
            {
                Index2i et = mesh.GetEdgeT(eid);
                if (mesh.GetTriangleGroup(et.a) != 0 || mesh.GetTriangleGroup(et.b) != 0)
                {
                    continue;
                }
                int gid = mesh.AllocateTriangleGroup();
                areas[gid]   = 0;
                trisets[gid] = new HashSet <int>();
                active_groups.Add(gid);
                add_tri_to_group(et.a, gid);
                add_tri_to_group(et.b, gid);
            }
            foreach (int tid in mesh.TriangleIndices())
            {
                if (mesh.GetTriangleGroup(tid) != 0)
                {
                    continue;
                }
                int gid = find_min_area_group(mesh.TriTrianglesItr(tid));
                add_tri_to_group(tid, gid);
            }


            IndexPriorityQueue pq = new IndexPriorityQueue(mesh.MaxGroupID);

            foreach (var pair in areas)
            {
                pq.Insert(pair.Key, (float)pair.Value);
            }
            while (pq.Count > 0)
            {
                int gid = pq.First;
                pq.Remove(gid);
                if (areas[gid] > minArea)                    // ??
                {
                    break;
                }

                List <int> nbr_groups = find_neighbour_groups(mesh, gid, trisets[gid]);
                int        min_gid = -1; double min_area = double.MaxValue;
                foreach (int ngid in nbr_groups)
                {
                    double a = areas[ngid];
                    if (a < min_area)
                    {
                        min_area = a;
                        min_gid  = ngid;
                    }
                }
                if (min_gid != -1)
                {
                    add_group_to_group(gid, min_gid);
                    pq.Remove(min_gid);
                    pq.Insert(min_gid, (float)areas[min_gid]);
                }
            }



            List <Polygon2d> result = new List <Polygon2d>();

            int[][] sets = FaceGroupUtil.FindTriangleSetsByGroup(mesh);
            foreach (var set in sets)
            {
                result.Add(make_poly(mesh, set));
            }
            return(result);
        }
        public virtual void Update()
        {
            base.begin_update();
            int start_timestamp = this.CurrentInputTimestamp;

            if (MeshSource == null)
            {
                throw new Exception("CombineMeshesOp: must set valid MeshSource to compute!");
            }

            ResultMesh = null;

            try {
                DMesh3 meshIn = new DMesh3(MeshSource.GetDMeshUnsafe());

                if (orient_nested_shells)
                {
                    MeshConnectedComponents comp = new MeshConnectedComponents(meshIn);
                    comp.FindConnectedT();
                    DSubmesh3Set subMeshes = new DSubmesh3Set(meshIn, comp);

                    List <DMesh3> curMeshes = new List <DMesh3>();
                    foreach (var submesh in subMeshes)
                    {
                        curMeshes.Add(submesh.SubMesh);
                    }

                    MeshSpatialSort sort = new MeshSpatialSort();
                    foreach (var mesh in curMeshes)
                    {
                        sort.AddMesh(mesh, mesh);
                    }
                    sort.Sort();

                    ResultMesh = new DMesh3();
                    MeshEditor editor = new MeshEditor(ResultMesh);
                    foreach (var solid in sort.Solids)
                    {
                        DMesh3 outer = solid.Outer.Mesh;
                        if (!is_outward_oriented(outer))
                        {
                            outer.ReverseOrientation();
                        }
                        editor.AppendMesh(outer, ResultMesh.AllocateTriangleGroup());

                        foreach (var hole in solid.Cavities)
                        {
                            if (hole.Mesh.CachedIsClosed && is_outward_oriented(hole.Mesh) == true)
                            {
                                hole.Mesh.ReverseOrientation();
                            }
                            editor.AppendMesh(hole.Mesh, ResultMesh.AllocateTriangleGroup());
                        }
                    }
                }
                else
                {
                    ResultMesh = meshIn;
                }

                base.complete_update();
            } catch (Exception e) {
                PostOnOperatorException(e);
                ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe());
                base.complete_update();
            }
        }