Esempio n. 1
0
        /// <summary>
        /// Find regions of the input meshes that are horizontal, returns binned by Z-value.
        /// Currently only finds upward-facing regions.
        /// </summary>
        protected Dictionary <double, List <PlanarRegion> > FindPlanarZRegions(double minDimension, double dotNormalTol = 0.999)
        {
            Dictionary <double, List <PlanarRegion> > Regions = new Dictionary <double, List <PlanarRegion> >();
            SpinLock region_lock = new SpinLock();

            gParallel.ForEach(Meshes, (sliceMesh) => {
                if (sliceMesh.options.IsCavity == false)
                {
                    return;
                }
                DMesh3 mesh = sliceMesh.mesh;

                HashSet <int> planar_tris = new HashSet <int>();
                foreach (int tid in mesh.TriangleIndices())
                {
                    Vector3d n = mesh.GetTriNormal(tid);
                    double dot = n.Dot(Vector3d.AxisZ);
                    if (dot > dotNormalTol)
                    {
                        planar_tris.Add(tid);
                    }
                }

                MeshConnectedComponents regions = new MeshConnectedComponents(mesh);
                regions.FilterF = planar_tris.Contains;
                regions.FindConnectedT();
                foreach (var c in regions)
                {
                    AxisAlignedBox3d bounds = MeshMeasurements.BoundsT(mesh, c.Indices);
                    if (bounds.Width > minDimension && bounds.Height > minDimension)
                    {
                        double z = Math.Round(bounds.Center.z, PrecisionDigits);

                        PlanarRegion planar = new PlanarRegion()
                        {
                            Mesh = mesh, Z = z, Triangles = c.Indices
                        };

                        bool taken = false;
                        region_lock.Enter(ref taken);
                        List <PlanarRegion> zregions;
                        if (Regions.TryGetValue(z, out zregions))
                        {
                            zregions.Add(planar);
                        }
                        else
                        {
                            zregions = new List <PlanarRegion>()
                            {
                                planar
                            };
                            Regions[z] = zregions;
                        }
                        region_lock.Exit();
                    }
                }
            });

            return(Regions);
        }
Esempio n. 2
0
        public static void RecenterPivot(FScene scene, DMeshSO so, PivotLocation location, bool bInteractive)
        {
            if (so.Parent != scene)
            {
                DebugUtil.Log("OrientationChanges.RecenterPivot: tried to recenter pivot on non-scene-child");
                return;
            }

            Frame3f          sceneL       = SceneTransforms.SceneToObject(so, Frame3f.Identity);
            AxisAlignedBox3d sceneBoundsL = AxisAlignedBox3d.Empty;

            so.SafeMeshRead((mesh) => {
                sceneBoundsL = MeshMeasurements.BoundsInFrame(mesh, sceneL);
                return(null);
            });

            Vector3d originL = sceneBoundsL.Center;

            if (location == PivotLocation.BaseCenter)
            {
                originL -= sceneBoundsL.Extents.y * Vector3d.AxisY;
            }
            Frame3f newFrameL = new Frame3f(originL);

            RepositionPivotChangeOp change = new RepositionPivotChangeOp(newFrameL, so);

            scene.History.PushChange(change, false);
            if (bInteractive)
            {
                scene.History.PushInteractionCheckpoint();
            }
        }
Esempio n. 3
0
        public static double GetVolume(MeshGeometry3D obj)
        {
            DMesh3 mesh      = MeshGeometryToDMesh(obj);
            var    triangles = mesh.TriangleIndices();
            Func <int, Vector3d> getVertexF = (a) =>
            {
                Vector3d V = mesh.GetVertex(a);
                return(V);
            };
            Vector2d Vol = MeshMeasurements.VolumeArea(mesh, triangles, getVertexF);

            return(Vol.x / 1000);
        }
Esempio n. 4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo goo = null;

            DA.GetData(0, ref goo);

            DMesh3 msh = new DMesh3(goo.Value);

            var volArea = MeshMeasurements.VolumeArea(msh, msh.TriangleIndices(), msh.GetVertex);

            DA.SetData(0, volArea[1]);
            DA.SetData(1, volArea[0]);
        }
Esempio n. 5
0
        public static double GetOverlapVolume(MeshGeometry3D obj1, MeshGeometry3D obj2)
        {
            DMesh3 mesh1     = MeshGeometryToDMesh(obj1);
            DMesh3 mesh2     = MeshGeometryToDMesh(obj2);
            DMesh3 MI        = BooleanIntersection(mesh1, mesh2);
            var    triangles = MI.TriangleIndices();
            Func <int, Vector3d> getVertexF = (a) =>
            {
                Vector3d V = MI.GetVertex(a);
                return(V);
            };
            Vector2d Vol = MeshMeasurements.VolumeArea(MI, triangles, getVertexF);

            return(Vol.x / 1000);
        }
        public void EndStroke()
        {
            if (CurrentStroke.Count >= 2)
            {
                DMesh3 mesh = Target.Mesh;

                TransformSequence toScene = SceneTransforms.ObjectToSceneXForm(Target);

                List <int> tris1 = new List <int>(), tris2 = new List <int>();
                Ray3f      first = CurrentStroke[0], last = CurrentStroke[CurrentStroke.Count - 1];

                Vector3f v0 = PlaneFrameS.RayPlaneIntersection(first.Origin, first.Direction, 2);
                Vector3f v1 = PlaneFrameS.RayPlaneIntersection(last.Origin, last.Direction, 2);

                Vector3f planeN = Vector3f.Cross(first.Direction, last.Direction);
                Frame3f  planeF = new Frame3f((v0 + v1) / 2, planeN);

                foreach (int tid in mesh.TriangleIndices())
                {
                    Vector3f c = (Vector3f)mesh.GetTriCentroid(tid);
                    c = toScene.TransformP(c);
                    if (planeF.DistanceToPlaneSigned(c, 2) < 0)
                    {
                        tris1.Add(tid);
                    }
                    else
                    {
                        tris2.Add(tid);
                    }
                }

                double area1 = MeshMeasurements.AreaT(mesh, tris1);
                double area2 = MeshMeasurements.AreaT(mesh, tris2);

                lastSelection = new MeshFaceSelection(mesh);
                lastSelection.Select((area1 > area2) ? tris2 : tris1);
                lastSelection.LocalOptimize();

                if (OnStrokeCompletedF != null)
                {
                    OnStrokeCompletedF(Target, lastSelection);
                }
            }

            CurrentStroke.Clear();
        }
Esempio n. 7
0
        public static List <double> Volumes(MeshGeometry3D mesh)
        {
            DMesh3 m3 = MeshGeometryToDMesh(mesh);

            DMesh3[]      mC      = MeshConnectedComponents.Separate(m3);
            List <double> ListVol = new List <double>();

            foreach (DMesh3 m in mC)
            {
                var triangles = m.TriangleIndices();
                Func <int, Vector3d> getVertexF = (a) =>
                {
                    Vector3d V = m.GetVertex(a);
                    return(V);
                };
                Vector2d Vol = MeshMeasurements.VolumeArea(m, triangles, getVertexF);
                ListVol.Add(Vol.x / 1000);
            }
            return(ListVol);
        }
Esempio n. 8
0
        /// <summary>
        /// when the socket is updated, shift the ground plane to be directly below it
        /// </summary>
        public static void AddRepositionGroundPlaneOnSocketEdit()
        {
            OG.OnSocketUpdated += () => {
                // compute scene-space bbox of socket mesh
                Frame3f          socketF = OG.Socket.Socket.GetLocalFrame(CoordSpace.ObjectCoords);
                AxisAlignedBox3d boundsS =
                    MeshMeasurements.Bounds(OG.Socket.Socket.Mesh, socketF.FromFrameP);

                // vertically translate bounds objects to be at same y
                //  (assumes they are xz planes!!)
                Vector3d baseS = boundsS.Center - boundsS.Extents[1] * Vector3d.AxisY;
                Vector3d baseW = OG.Scene.ToWorldP(baseS);
                foreach (var go in OG.Scene.BoundsObjects)
                {
                    Vector3f pos = go.GetPosition();
                    pos.y = (float)baseW.y;
                    go.SetPosition(pos);
                }
            };
        }
        public virtual void Update()
        {
            if (MeshSource == null)
            {
                throw new Exception("LegSqueezeOp: must set valid MeshSource to compute!");
            }

            IMesh mesh = MeshSource.GetIMesh();

            if (mesh.HasVertexNormals == false)
            {
                throw new Exception("LegSqueezeOp: input mesh does not have surface normals...");
            }

            Displacement.Resize(mesh.MaxVertexID);

            // compute extents along axis
            double     upper_t      = UpperPoint.Dot(Axis);
            Interval1d axis_extents = MeshMeasurements.ExtentsOnAxis(mesh, axis);
            double     lower_t      = axis_extents.a;


            // compute approximate skeleton
            int nVertices = midPoints.Count + 2;

            Vector3d[] centers = new Vector3d[nVertices];
            int[]      counts  = new int[nVertices];
            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v    = mesh.GetVertex(vid);
                double   t    = v.Dot(ref axis);
                int      iBin = 0;
                if (t > upper_t)
                {
                    iBin = nVertices - 1;
                }
                else if (t > lower_t)
                {
                    double unit_t = (t - lower_t) / (upper_t - lower_t);
                    iBin = 1;
                    for (int k = 0; k < midPoints.Count; ++k)
                    {
                        if (unit_t > midPoints[k].x)
                        {
                            iBin++;
                        }
                    }
                }   // else iBin = 0, as initialized
                centers[iBin] += v;
                counts[iBin]++;
            }
            for (int k = 0; k < centers.Length; ++k)
            {
                centers[k] /= counts[k];
            }


            // todo: can do this in parallel
            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v = mesh.GetVertex(vid);
                double   t = v.Dot(axis);
                if (t > upper_t)
                {
                    continue;
                }

                Vector3d center  = centers[0];
                double   percent = 0;

                if (t >= upper_t)
                {
                    percent = reduce_percent_top;
                    center  = centers[nVertices - 1];
                }
                else if (t <= lower_t)
                {
                    percent = reduce_percent_bottom;
                    center  = centers[0];
                }
                else if (midPoints.Count == 0)
                {
                    double unit_t = (t - lower_t) / (upper_t - lower_t);
                    unit_t  = MathUtil.WyvillRise01(unit_t);
                    percent = MathUtil.Lerp(reduce_percent_bottom, reduce_percent_top, unit_t);
                }
                else
                {
                    double   unit_t = (t - lower_t) / (upper_t - lower_t);
                    double   low_percent = reduce_percent_bottom;
                    double   high_percent = reduce_percent_top;
                    Vector3d low_center = centers[0];
                    Vector3d high_center = centers[0];
                    double   low_t = 0.0, high_t = 0;
                    for (int i = 0; i < midPoints.Count; ++i)
                    {
                        if (unit_t < midPoints[i].x)
                        {
                            high_t       = midPoints[i].x;
                            high_percent = midPoints[i].y;
                            high_center  = centers[i + 1];
                            break;
                        }
                        low_t       = midPoints[i].x;
                        low_percent = midPoints[i].y;
                        low_center  = centers[i + 1];
                    }
                    if (high_t == 0)
                    {
                        high_t       = 1.0;
                        high_percent = reduce_percent_top;
                        high_center  = centers[nVertices - 1];
                    }
                    double a = (unit_t - low_t) / (high_t - low_t);
                    a       = MathUtil.WyvillRise01(a);
                    percent = MathUtil.Lerp(low_percent, high_percent, a);
                    center  = Vector3d.Lerp(low_center, high_center, a);
                }

                percent = percent / 100;

                double   scale    = 1.0 - percent;
                Vector3d v_scaled = (v - center) * new Vector3d(scale, 1, scale) + center;
                Displacement[vid] = v_scaled - v;
            }

            result_valid = true;
        }
Esempio n. 10
0
        /// <summary>
        /// This is the action we give to the trim-scan tool, to run on accept
        /// </summary>
        public static void CropScanFromSelection(DMeshSO so, MeshFaceSelection selection, object tool)
        {
            DMesh3 beforeMesh = new DMesh3(so.Mesh);
            DMesh3 mesh       = so.Mesh;

            // [RMS] if we are using the two-point tool, then we can use the user input points to
            // try to figure out an up axis, by assuming the first point is on the base of the scan. Steps are:
            //   1) guess a midpoint. Currently centroid of upper-half of geodesic selection.
            //   2) construct up axis as (midpoint-basepoint). this axis to Y-up.
            Vector3f upAxisS = Vector3f.AxisY;
            TwoPointFaceSelectionTool ptool = tool as TwoPointFaceSelectionTool;

            if (ptool != null)
            {
                var        cache     = ptool.SelectionCache;
                Interval1d range     = new Interval1d(cache.CurrentScalarThreshold / 2, cache.CurrentScalarThreshold);
                List <int> triangles = new List <int>(selection.Count);
                cache.FindTrianglesInScalarInterval(range, triangles);
                Vector3d c        = MeshMeasurements.Centroid(triangles, mesh.GetTriCentroid);
                Vector3d cS       = SceneTransforms.ObjectToSceneP(so, c);
                Vector3d basePosS = ptool.SourcePositionS.Origin;
                upAxisS = (Vector3f)(cS - basePosS).Normalized;
            }

            // crop scan and fill top hole
            List <int> borderTris = selection.FindBorderTris();
            MeshEditor editor     = new MeshEditor(mesh);

            editor.RemoveTriangles((tid) => { return(selection.IsSelected(tid) == false); }, true);
            if (OGActions.FillHoleInScan)
            {
                SmoothedHoleFill fill = new SmoothedHoleFill(mesh)
                {
                    TargetEdgeLength = 2.5f,
                    SmoothAlpha      = 0.5f,
                    BorderHintTris   = borderTris,
                    OffsetDirection  = SceneTransforms.SceneToObjectN(so, upAxisS),
                    OffsetDistance   = (ptool != null) ? 25.0 : 0.0
                };
                fill.Apply();
            }

            so.NotifyMeshEdited();
            DMesh3 afterMesh = new DMesh3(so.Mesh);

            so.GetScene().History.PushChange(new ReplaceEntireMeshChange(so, beforeMesh, afterMesh), true);
            mesh = so.Mesh;

            // Now we auto-align the scan so it points upwards, and then
            // recenter pivot and shift to above ground plane
            if (ptool != null)
            {
                Vector3d    basePosS = ptool.SourcePositionS.Origin;
                Quaternionf alignUp  = Quaternionf.FromTo(upAxisS, Vector3f.AxisY);

                // rotate part so that axis points up
                Frame3f           curF          = so.GetLocalFrame(CoordSpace.SceneCoords);
                Frame3f           newF          = curF.Rotated(alignUp);
                TransformSOChange alignUpChange = new TransformSOChange(so, curF, newF, CoordSpace.SceneCoords);
                basePosS = newF.FromFrameP(curF.ToFrameP(basePosS));   // map to new frame
                so.GetScene().History.PushChange(alignUpChange, false);

                // recenter pivot at bbox center
                // [RMS] previously was using vertex centroid, but this is then affected by mesh density
                //   (maybe tri centroid? but bbox makes more sense...and below we assume box center)
                Vector3d centerL   = mesh.CachedBounds.Center;
                Vector3d centerO   = newF.FromFrameP(centerL);
                Frame3f  newPivotO = new Frame3f(centerO);
                so.GetScene().History.PushChange(new RepositionPivotChangeOp(newPivotO, so), false);

                // position above ground plane
                AxisAlignedBox3d bounds     = so.Mesh.CachedBounds;
                float            h          = (float)bounds.Height;
                Vector3f         o          = newPivotO.Origin;
                Vector3f         translateO = new Vector3f(-o.x, h * 0.5f - o.y + BaseHeightAboveGroundPlaneMM, -o.z);
                //Vector3f translateO = new Vector3f(0, h * 0.5f - o.y + BaseHeightAboveGroundPlaneMM, 0);
                newPivotO.Translate(translateO);
                so.GetScene().History.PushChange(new TransformSOChange(so, newPivotO, CoordSpace.ObjectCoords), false);

                // save base point in frame of scan
                basePosS += translateO;
                Vector3d basePosL = SceneTransforms.SceneToObjectP(so, basePosS);
                OG.Scan.UserBasePoint = basePosL;
            }

            so.GetScene().History.PushInteractionCheckpoint();
        }