Пример #1
0
 /// <summary>
 /// Converts the provided double vector from g3 into the OpenTK variant.
 /// </summary>
 /// <param name="vector">The vector to convert from its current double variant.
 /// </param>
 /// <returns>An OpenTK vector to use in all calculations.</returns>
 public static Vector3 VectorConvert(g3.Vector3d vector)
 {
     return(new Vector3(
                Convert.ToSingle(vector.x),
                Convert.ToSingle(vector.y),
                Convert.ToSingle(vector.z)
                ));
 }
Пример #2
0
            double GetNormalQuality(g3.DMesh3 mesh, g3.Vector3d target, int depth)
            {
                if (depth == 0)
                {
                    return(1 - (mesh.GetTriNormal(meshIndex).Dot(target)));
                }

                double amount = GetNormalQuality(mesh, target, 0);

                foreach (var n in neighbors)
                {
                    amount += GetNormalQuality(mesh, target, depth - 1);
                }

                return(amount);
            }
Пример #3
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            DMesh3           mesh   = new DMesh3(MakeRemeshedCappedCylinder(1.0), true);
            AxisAlignedBox3d bounds = mesh.GetBounds();

            List <IMesh> result_meshes = new List <IMesh>();

            LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh);

            // constrain bottom points
            foreach (int vid in mesh.VertexIndices())
            {
                g3.Vector3d v      = mesh.GetVertex(vid);
                bool        bottom = (v.y - bounds.Min.y) < 0.01f;
                if (bottom)
                {
                    deformer.SetConstraint(vid, v, 10);
                }
            }

            // constrain one other vtx
            int ti    = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new g3.Vector3d(2, 5, 2));
            int v_pin = mesh.GetTriangle(ti).a;

            g3.Vector3d cons_pos = mesh.GetVertex(v_pin);
            cons_pos += new g3.Vector3d(0.5, 0.5, 0.5);
            deformer.SetConstraint(v_pin, cons_pos, 10);


            deformer.Initialize();
            g3.Vector3d[] resultV = new g3.Vector3d[mesh.MaxVertexID];
            deformer.Solve(resultV);

            foreach (int vid in mesh.VertexIndices())
            {
                mesh.SetVertex(vid, resultV[vid]);
            }


            var rhinoMesh = GopherUtil.ConvertToRhinoMesh(mesh);

            doc.Objects.AddMesh(rhinoMesh);

            return(Result.Success);
        }
Пример #4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            int        num_cells = 128;
            DMesh3_goo dMsh_goo  = null;

            DA.GetData(0, ref dMsh_goo);
            DA.GetData(1, ref num_cells);

            DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value);
            double cell_size = dMsh_copy.CachedBounds.MaxDim / num_cells;

            DMeshAABBTree3 spatial = new DMeshAABBTree3(dMsh_copy, autoBuild: true);

            AxisAlignedBox3d  bounds   = dMsh_copy.CachedBounds;
            double            cellsize = bounds.MaxDim / num_cells;
            ShiftGridIndexer3 indexer  = new ShiftGridIndexer3(bounds.Min, cellsize);

            Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells));

            foreach (Vector3i idx in bmp.Indices())
            {
                g3.Vector3d v = indexer.FromGrid(idx);
                bmp.Set(idx, spatial.IsInside(v));
            }

            VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator();

            voxGen.Voxels = bmp;
            voxGen.Generate();
            DMesh3 voxMesh = voxGen.Meshes[0];

            var vecSize = dMsh_copy.CachedBounds.Extents;
            var box     = dMsh_copy.GetBounds();

            // Scale voxel mesh
            //MeshTransforms.Scale(voxMesh,)

            DA.SetData(0, voxMesh);
        }
Пример #5
0
        public static DMesh3 MineCraft(DMesh3 mesh, int num_cells, out double scalefactor)
        {
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, autoBuild: true);


            AxisAlignedBox3d bounds   = mesh.CachedBounds;
            double           cellsize = bounds.MaxDim / num_cells;

            scalefactor = cellsize;

            ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min, cellsize);

            Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells));

            foreach (Vector3i idx in bmp.Indices())
            {
                g3.Vector3d v = indexer.FromGrid(idx);
                if (spatial.IsInside(v))
                {
                    bmp.Set(idx, true);
                }
                else
                {
                    bmp.Set(idx, false);
                }
            }

            VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator();

            voxGen.Voxels = bmp;
            voxGen.Generate();

            DMesh3 voxMesh = voxGen.Meshes[0];

            return(voxMesh);
        }
Пример #6
0
 public static Point3d ToRhinoPoint(this g3.Vector3d v)
 {
     return(new Point3d(v.x, v.y, v.z));
 }
Пример #7
0
 public static Vector3d ToRhinoVector(this g3.Vector3d v)
 {
     return(new Vector3d(v.x, v.y, v.z));
 }
Пример #8
0
        //public static void VoronoiMesh(List<g3.PolyLine3d> mesh, out List<g3.Line3d> listLines, out List<g3.PolyLine3d> listPolylines)
        //{
        //    System.Collections.Generic.SortedDictionary<int, MeshNode> faces = new System.Collections.Generic.SortedDictionary<int, MeshNode>();

        //    int index = 0;
        //    foreach (var meshFaceIndex in mesh.TriangleIndices())
        //    {
        //        var frame = mesh.GetTriFrame(meshFaceIndex);

        //        g3.Index3i neighbors = mesh.GetTriNeighbourTris(meshFaceIndex);
        //        g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex);

        //        faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index));
        //    }


        //    foreach (var f in faces)
        //    {
        //        f.Value.neighbors.Clear();
        //        f.Value.neighbors.Capacity = 3;
        //        for (int i = 0; i < 3; ++i)
        //        {
        //            int fn = f.Value.neighbors_index[i];
        //            if (fn >= 0)
        //                f.Value.neighbors.Add(faces[fn]);
        //        }

        //        if (f.Value.neighbors.Count < 3)
        //        {
        //            f.Value.locked = true;

        //            foreach (var n in f.Value.neighbors)
        //                n.locked = true;
        //        }
        //    }

        //    outputMesh = new g3.DMesh3(g3.MeshComponents.None);
        //    listLines = new List<g3.Line3d>();
        //    listPolylines = new List<g3.PolyLine3d>();
        //    foreach (var f in faces)
        //    {
        //        outputMesh.AppendVertex(f.Value.frame.Origin);
        //    }

        //    HashSet<int> processedPoints = new HashSet<int>();

        //    foreach (var f in faces)
        //    {
        //        for (int i = 0; i < 3; i++)
        //        {
        //            List<int> outputLine = new List<int>();

        //            if (processedPoints.Contains(f.Value.vertex_index[i]))
        //                continue;

        //            int checkVertex = f.Value.vertex_index[i];

        //            MeshNode currentFaces = f.Value;
        //            MeshNode prevFace = null;

        //            bool fullLoop = false;

        //            while (true)
        //            {
        //                for (int j = 0; j < currentFaces.neighbors.Count; j++)
        //                {

        //                    var neighbor = currentFaces.neighbors[j];
        //                    if (neighbor.UsesVertex(checkVertex))
        //                    {

        //                        if (neighbor == prevFace)
        //                            continue;

        //                        if (neighbor == f.Value)
        //                        {
        //                            fullLoop = true;
        //                            break; // Found full loop
        //                        }

        //                        outputLine.Add(neighbor.index);

        //                        prevFace = currentFaces;
        //                        currentFaces = neighbor;
        //                        j = -1;
        //                    }
        //                }

        //                break;
        //            }

        //            if (fullLoop)
        //            {
        //                processedPoints.Add(checkVertex);

        //                var polyline = new g3.PolyLine3d();

        //                if (outputLine.Count > 2)
        //                {
        //                    g3.Vector3d centerPoint = f.Value.frame.Origin;

        //                    foreach (var p in outputLine)
        //                        centerPoint += outputMesh.GetVertex(p);

        //                    centerPoint /= (outputLine.Count + 1);

        //                    int center = outputMesh.AppendVertex(centerPoint);

        //                    var pS = outputMesh.GetVertex(f.Value.index);
        //                    var p0 = outputMesh.GetVertex(outputLine[0]);
        //                    var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]);

        //                    var normal = mesh.GetTriNormal(f.Value.meshIndex);

        //                    polyline.AppendVertex(pS);
        //                    polyline.AppendVertex(p0);

        //                    listLines.Add(new g3.Line3d(pS, p0 - pS));

        //                    var n = MathUtil.Normal(centerPoint, pS, p0);

        //                    bool reverseTri = n.Dot(normal) < 0;

        //                    if (!reverseTri)
        //                        outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]);
        //                    else
        //                        outputMesh.AppendTriangle(center, outputLine[0], f.Value.index);

        //                    for (int j = 0; j < outputLine.Count - 1; j++)
        //                    {
        //                        var p1 = outputMesh.GetVertex(outputLine[j]);
        //                        var p2 = outputMesh.GetVertex(outputLine[j + 1]);

        //                        listLines.Add(new g3.Line3d(p1, p2 - p1));
        //                        polyline.AppendVertex(p2);

        //                        if (!reverseTri)
        //                            outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]);
        //                        else
        //                            outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]);
        //                    }

        //                    polyline.AppendVertex(pS);
        //                    listLines.Add(new g3.Line3d(pE, pS - pE));

        //                    listPolylines.Add(polyline);

        //                    if (!reverseTri)
        //                        outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index);
        //                    else
        //                        outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]);
        //                }
        //            }
        //        }

        //    }
        //}

        public static void VoronoiMesh(g3.DMesh3 mesh, out g3.DMesh3 outputMesh, out List <g3.Line3d> listLines, out List <g3.PolyLine3d> listPolylines)
        {
            System.Collections.Generic.SortedDictionary <int, MeshNode> faces = new System.Collections.Generic.SortedDictionary <int, MeshNode>();

            int index = 0;

            foreach (var meshFaceIndex in mesh.TriangleIndices())
            {
                var frame = mesh.GetTriFrame(meshFaceIndex);

                g3.Index3i neighbors    = mesh.GetTriNeighbourTris(meshFaceIndex);
                g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex);

                faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index));
            }


            foreach (var f in faces)
            {
                f.Value.neighbors.Clear();
                f.Value.neighbors.Capacity = 3;
                for (int i = 0; i < 3; ++i)
                {
                    int fn = f.Value.neighbors_index[i];
                    if (fn >= 0)
                    {
                        f.Value.neighbors.Add(faces[fn]);
                    }
                }

                if (f.Value.neighbors.Count < 3)
                {
                    f.Value.locked = true;

                    foreach (var n in f.Value.neighbors)
                    {
                        n.locked = true;
                    }
                }
            }

            outputMesh    = new g3.DMesh3(g3.MeshComponents.None);
            listLines     = new List <g3.Line3d>();
            listPolylines = new List <g3.PolyLine3d>();
            foreach (var f in faces)
            {
                outputMesh.AppendVertex(f.Value.frame.Origin);
            }

            HashSet <int> processedPoints = new HashSet <int>();

            foreach (var f in faces)
            {
                for (int i = 0; i < 3; i++)
                {
                    List <int> outputLine = new List <int>();

                    if (processedPoints.Contains(f.Value.vertex_index[i]))
                    {
                        continue;
                    }

                    int checkVertex = f.Value.vertex_index[i];

                    MeshNode currentFaces = f.Value;
                    MeshNode prevFace     = null;

                    bool fullLoop = false;

                    while (true)
                    {
                        for (int j = 0; j < currentFaces.neighbors.Count; j++)
                        {
                            var neighbor = currentFaces.neighbors[j];
                            if (neighbor.UsesVertex(checkVertex))
                            {
                                if (neighbor == prevFace)
                                {
                                    continue;
                                }

                                if (neighbor == f.Value)
                                {
                                    fullLoop = true;
                                    break; // Found full loop
                                }

                                outputLine.Add(neighbor.index);

                                prevFace     = currentFaces;
                                currentFaces = neighbor;
                                j            = -1;
                            }
                        }

                        break;
                    }

                    if (fullLoop)
                    {
                        processedPoints.Add(checkVertex);

                        var polyline = new g3.PolyLine3d();

                        if (outputLine.Count > 2)
                        {
                            g3.Vector3d centerPoint = f.Value.frame.Origin;

                            foreach (var p in outputLine)
                            {
                                centerPoint += outputMesh.GetVertex(p);
                            }

                            centerPoint /= (outputLine.Count + 1);

                            int center = outputMesh.AppendVertex(centerPoint);

                            var pS = outputMesh.GetVertex(f.Value.index);
                            var p0 = outputMesh.GetVertex(outputLine[0]);
                            var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]);

                            var normal = mesh.GetTriNormal(f.Value.meshIndex);

                            polyline.AppendVertex(pS);
                            polyline.AppendVertex(p0);

                            listLines.Add(new g3.Line3d(pS, p0 - pS));

                            var n = MathUtil.Normal(centerPoint, pS, p0);

                            bool reverseTri = n.Dot(normal) < 0;

                            if (!reverseTri)
                            {
                                outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]);
                            }
                            else
                            {
                                outputMesh.AppendTriangle(center, outputLine[0], f.Value.index);
                            }

                            for (int j = 0; j < outputLine.Count - 1; j++)
                            {
                                var p1 = outputMesh.GetVertex(outputLine[j]);
                                var p2 = outputMesh.GetVertex(outputLine[j + 1]);

                                listLines.Add(new g3.Line3d(p1, p2 - p1));
                                polyline.AppendVertex(p2);

                                if (!reverseTri)
                                {
                                    outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]);
                                }
                                else
                                {
                                    outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]);
                                }
                            }

                            polyline.AppendVertex(pS);
                            listLines.Add(new g3.Line3d(pE, pS - pE));

                            listPolylines.Add(polyline);

                            if (!reverseTri)
                            {
                                outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index);
                            }
                            else
                            {
                                outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]);
                            }
                        }
                    }
                }
            }
        }
Пример #9
0
        protected virtual ProcessResult CollapseEdge(int edgeID, Vector3d vNewPos, out int collapseToV)
        {
            collapseToV = DMesh3.InvalidID;
            RuntimeDebugCheck(edgeID);

            EdgeConstraint constraint =
                (constraints == null) ? EdgeConstraint.Unconstrained : constraints.GetEdgeConstraint(edgeID);

            if (constraint.NoModifications)
            {
                return(ProcessResult.Ignored_EdgeIsFullyConstrained);
            }
            if (constraint.CanCollapse == false)
            {
                return(ProcessResult.Ignored_EdgeIsFullyConstrained);
            }


            // look up verts and tris for this edge
            int a = 0, b = 0, t0 = 0, t1 = 0;

            if (mesh.GetEdge(edgeID, ref a, ref b, ref t0, ref t1) == false)
            {
                return(ProcessResult.Failed_NotAnEdge);
            }
            bool bIsBoundaryEdge = (t1 == DMesh3.InvalidID);

            // look up 'other' verts c (from t0) and d (from t1, if it exists)
            Index3i T0tv         = mesh.GetTriangle(t0);
            int     c            = IndexUtil.find_tri_other_vtx(a, b, T0tv);
            Index3i T1tv         = (bIsBoundaryEdge) ? DMesh3.InvalidTriangle : mesh.GetTriangle(t1);
            int     d            = (bIsBoundaryEdge) ? DMesh3.InvalidID : IndexUtil.find_tri_other_vtx(a, b, T1tv);

            Vector3d vA           = mesh.GetVertex(a);
            Vector3d vB           = mesh.GetVertex(b);
            double   edge_len_sqr = (vA - vB).LengthSquared;

            if (edge_len_sqr > MinEdgeLength * MinEdgeLength)
            {
                return(ProcessResult.Ignored_EdgeTooLong);
            }

            begin_collapse();

            // check if we should collapse, and also find which vertex we should collapse to,
            // in cases where we have constraints/etc
            int  collapse_to  = -1;
            bool bCanCollapse = can_collapse_constraints(edgeID, a, b, c, d, t0, t1, out collapse_to);

            if (bCanCollapse == false)
            {
                return(ProcessResult.Ignored_Constrained);
            }

            // if we have a boundary, we want to collapse to boundary
            if (PreserveBoundary && HaveBoundary)
            {
                if (collapse_to != -1)
                {
                    if ((IsBoundaryV(b) && collapse_to != b) ||
                        (IsBoundaryV(a) && collapse_to != a))
                    {
                        return(ProcessResult.Ignored_Constrained);
                    }
                }
                if (IsBoundaryV(b))
                {
                    collapse_to = b;
                }
                else if (IsBoundaryV(a))
                {
                    collapse_to = a;
                }
            }

            // optimization: if edge cd exists, we cannot collapse or flip. look that up here?
            //  funcs will do it internally...
            //  (or maybe we can collapse if cd exists? edge-collapse doesn't check for it explicitly...)
            ProcessResult retVal = ProcessResult.Failed_OpNotSuccessful;

            int iKeep = b, iCollapse = a;

            // if either vtx is fixed, collapse to that position
            if (collapse_to == b)
            {
                vNewPos = vB;
            }
            else if (collapse_to == a)
            {
                iKeep   = a; iCollapse = b;
                vNewPos = vA;
            }
            else
            {
                vNewPos = get_projected_collapse_position(iKeep, vNewPos);
            }

            // check if this collapse will create a normal flip. Also checks
            // for invalid collapse nbrhood, since we are doing one-ring iter anyway.
            // [TODO] could we skip this one-ring check in CollapseEdge? pass in hints?
            if (creates_flip_or_invalid(a, b, vNewPos, t0, t1) || creates_flip_or_invalid(b, a, vNewPos, t0, t1))
            {
                retVal = ProcessResult.Ignored_CreatesFlip;
                goto skip_to_end;
            }

            // lots of cases where we cannot collapse, but we should just let
            // mesh sort that out, right?
            COUNT_COLLAPSES++;
            DMesh3.EdgeCollapseInfo collapseInfo;
            MeshResult result = mesh.CollapseEdge(iKeep, iCollapse, out collapseInfo);

            if (result == MeshResult.Ok)
            {
                collapseToV = iKeep;
                mesh.SetVertex(iKeep, vNewPos);
                if (constraints != null)
                {
                    constraints.ClearEdgeConstraint(edgeID);
                    constraints.ClearEdgeConstraint(collapseInfo.eRemoved0);
                    if (collapseInfo.eRemoved1 != DMesh3.InvalidID)
                    {
                        constraints.ClearEdgeConstraint(collapseInfo.eRemoved1);
                    }
                    constraints.ClearVertexConstraint(iCollapse);
                }
                OnEdgeCollapse(edgeID, iKeep, iCollapse, collapseInfo);
                DoDebugChecks();

                retVal = ProcessResult.Ok_Collapsed;
            }

skip_to_end:
            end_collapse();
            return(retVal);
        }
Пример #10
0
 public QEdge(int edge_id, QuadricError qin, Vector3d pt)
 {
     eid         = edge_id;
     q           = qin;
     collapse_pt = pt;
 }