public void Initialize_AutoFitBox()
        {
            DMeshSO TargetMeshSO = TargetSO as DMeshSO;

            // initialize w/ auto-fit box
            DMesh3         mesh    = TargetMeshSO.Mesh;
            DMeshAABBTree3 spatial = TargetMeshSO.Spatial;

            meshBounds = mesh.CachedBounds;

            create_preview_so();

            ContOrientedBox3 boxFitter = new ContOrientedBox3(
                new RemapItr <Vector3d, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriCentroid(tid)); }),
                new RemapItr <double, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriArea(tid)); }));
            //DebugUtil.EmitDebugBox("fitbox", boxFitter.Box, Colorf.Red, TargetSO.RootGameObject, false);
            Box3d fitBox  = boxFitter.Box;
            int   longest = 0;

            if (fitBox.Extent.y > fitBox.Extent.x)
            {
                longest = 1;
            }
            if (fitBox.Extent.z > fitBox.Extent[longest])
            {
                longest = 2;
            }
            Vector3d vTop    = fitBox.Center + fitBox.Extent[longest] * fitBox.Axis(longest);
            Vector3d vBottom = fitBox.Center - fitBox.Extent[longest] * fitBox.Axis(longest);

            int base_tid = spatial.FindNearestTriangle(vBottom);
            int top_tid  = spatial.FindNearestTriangle(vTop);

            if (vTop.y < vBottom.y)
            {
                int tmp = base_tid; base_tid = top_tid; top_tid = tmp;
            }
            Vector3d vBasePt = mesh.GetTriCentroid(base_tid);
            Vector3d vTopPt  = mesh.GetTriCentroid(top_tid);


            int      other1 = (longest + 1) % 3, other2 = (longest + 2) % 3;
            int      front_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other1)));
            Vector3d vFrontPt  = mesh.GetTriCentroid(front_tid);

            int      back_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other1)));
            Vector3d vBackPt  = mesh.GetTriCentroid(back_tid);

            int      right_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other2)));
            Vector3d vRightPt  = mesh.GetTriCentroid(right_tid);

            int      left_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other2)));
            Vector3d vLeftPt  = mesh.GetTriCentroid(left_tid);

            initialFrontPt = (Vector3f)vFrontPt;

            SetPointPosition_Internal(BasePointID, MeshQueries.SurfaceFrame(mesh, base_tid, vBasePt), CoordSpace.ObjectCoords);
            SetPointPosition_Internal(FrontPointID, MeshQueries.SurfaceFrame(mesh, front_tid, vFrontPt), CoordSpace.ObjectCoords);
            SetPointPosition(TopPointID, MeshQueries.SurfaceFrame(mesh, top_tid, vTopPt), CoordSpace.ObjectCoords);
        }
Example #2
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);
        }