Beispiel #1
0
        // iterate through the grid in the x directions
        /// <summary>
        ///   Iterate through the grid and add voxels that are inside the Brep
        /// </summary>
        /// <param name="brepVolume"></param>
        /// <param name="vg"></param>
        public void AddSolidBrep(Brep brepVolume, ref VoxelGrid3D vg)
        {
            // get the axis direction for each point
            var pt1 = vg.EvaluatePoint(new Point3i(0, 0, 0));
            var pt2 = vg.EvaluatePoint(new Point3i(1, 0, 0));
            var pln = new Plane(pt1, (pt2 - pt1));

            for (var x = 0; x < vg.SizeUVW.X; x++)
            {
                pln.Origin = vg.EvaluatePoint(new Point3i(x, 0, 0));
                Intersection.BrepPlane(brepVolume, pln, DocumentHelper.GetModelTolerance(), out var sections, out var pts);
                var surfaces = Brep.CreatePlanarBreps(sections);

                // perhaps check first if the points are inside the bounding box of the surface.
                if (surfaces == null)
                {
                    continue;
                }

                for (var y = 0; y < vg.SizeUVW.Y; y++)
                {
                    for (var z = 0; z < vg.SizeUVW.Z; z++)
                    {
                        var pt       = vg.EvaluatePoint(new Point3i(x, y, z));
                        var hasPixel = surfaces.Any(t => t.ClosestPoint(pt).DistanceTo(pt) < DocumentHelper.GetModelTolerance());
                        if (hasPixel)
                        {
                            vg.SetValue(new Point3i(x, y, z), true);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Adds the mesh.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <param name="vg">The vg.</param>
        private void AddMesh(Mesh m, ref VoxelGrid3D vg)
        {
            if (Distance < RhinoMath.ZeroTolerance)
            {
                // add closed mesh
                var bb     = m.GetBoundingBox(true);
                var length = bb.Diagonal.Length * 1.1;
                for (var i = 0; i < vg.Count; i++)
                {
                    var pt       = vg.EvaluatePoint(i);
                    var isInside = false;
                    if (bb.Contains(pt))
                    {
                        Intersection.MeshLine(m, new Line(pt, Vector3d.XAxis, length), out var faces);
                        if (faces != null)
                        {
                            isInside = faces.Length % 2 == 1;
                        }
                    }
                    if (isInside)
                    {
                        vg.SetValue(i, true);
                    }
                }
            }
            else
            {
                // add open mesh
                var bb = m.GetBoundingBox(true);
                bb.Inflate(Distance * 0.6);
                for (var i = 0; i < vg.Count; i++)
                {
                    var isInside = false;
                    var pt       = vg.EvaluatePoint(i);
                    if (bb.Contains(pt))
                    {
                        var foundPoint = m.ClosestPoint(pt);

                        if (foundPoint.DistanceTo(pt) <= Distance)
                        {
                            isInside = true;
                        }
                    }
                    if (isInside)
                    {
                        vg[i] = true;
                    }
                }
            }
        }
Beispiel #3
0
 /// <summary>
 ///   Add point to the grid.
 /// </summary>
 /// <param name="pt">Point in world space</param>
 /// <param name="vg">Voxelgrid</param>
 public void AddPt(Point3d pt, ref VoxelGrid3D vg)
 {
     if (Distance < RhinoMath.ZeroTolerance)
     {
         var pti = vg.ClosestPoint(pt);
         if (pti >= Point3i.Origin && pti <= vg.SizeUVW)
         {
             vg.SetValue(pti, true);
         }
     }
     else
     {
         var bb = new BoundingBox(new [] { pt });
         bb.Inflate(Distance * 1.1);
         foreach (var subPt in vg.PointsInBox(bb))
         {
             if (vg.PointInGrid(subPt) &&
                 !vg[subPt] &&
                 vg.EvaluatePoint(subPt).DistanceTo(pt) < Distance)
             {
                 vg[subPt] = true;
             }
         }
     }
 }
Beispiel #4
0
        /// <summary>
        /// Create a mesh quad from a voxelgrid
        /// </summary>
        /// <param name="vg">VoxelGrid</param>
        /// <param name="i">The voxel number in the grid</param>
        /// <param name="faceId">The id of the face (faces are defined in FaceDirections)</param>
        /// <param name="m">The mesh to add the face to</param>
        /// <param name="FaceDirections">(Predefined) List of directions for each face</param>
        /// <param name="AxisDirections">(Predefined) List of directions of Axis (x,y,z)</param>
        /// <param name="FaceAxis">(Predefined) Define which axis lies on which plane</param>
        public static void AddFacadeToMesh(VoxelGrid3D vg, int i, int faceId, ref Mesh m, Vector3d[] FaceDirections, Vector3d[] AxisDirections, int[,] FaceAxis)
        {
            // 0 for x, 1 for y, 2 for z
            int iDir = Convert.ToInt16(Math.Floor((double)faceId / 2));
            // get the position and the location
            var position = vg.EvaluatePoint(i);

            // to determine the correct position of the plane
            // we have to aim the x or y direction
            var distance = FaceDirections[faceId] * (vg.VoxelSize[iDir] * 0.5);

            position.Transform(Transform.Translation(distance));

            var pln = new Plane(position, AxisDirections[FaceAxis[iDir, 0]], AxisDirections[FaceAxis[iDir, 1]]);

            //planes.Add(pln);
            var sizeU = vg.VoxelSize[FaceAxis[iDir, 0]] / 2;
            var sizeV = vg.VoxelSize[FaceAxis[iDir, 1]] / 2;

            var pts = new Point3d[] {
                new Point3d(-sizeU, -sizeV, 0),
                new Point3d(-sizeU, sizeV, 0),
                new Point3d(sizeU, sizeV, 0),
                new Point3d(sizeU, -sizeV, 0)
            };

            var p3fs = new List <Point3f>();

            foreach (var ptd in pts)
            {
                var worldpt = pln.PointAt(ptd.X, ptd.Y, ptd.Z);
                p3fs.Add(new Point3f((float)worldpt.X, (float)worldpt.Y, (float)worldpt.Z));
            }


            // try to use unique vertices
            var cCount = m.Vertices.Count;

            m.Vertices.AddVertices(p3fs);
            var iFaceIndex = m.Faces.Count;
            var facenormal = Vector3d.CrossProduct(p3fs[1] - p3fs[0], p3fs[2] - p3fs[0]);

            if (Vector3d.VectorAngle(facenormal, FaceDirections[faceId]) > Math.PI / 2)
            {
                m.Faces.AddFace(cCount + 3, cCount + 2, cCount + 1, cCount);
            }
            else
            {
                m.Faces.AddFace(cCount, cCount + 1, cCount + 2, cCount + 3);
            }
            m.FaceNormals.SetFaceNormal(iFaceIndex, FaceDirections[faceId]);
        }
Beispiel #5
0
        private void AddBox(Box oBox, ref VoxelGrid3D vg)
        {
            var newBox = oBox.BoundingBox;

            for (var i = 0; i < vg.Count; i++)
            {
                var pt = vg.EvaluatePoint(i);
                if (newBox.Contains(pt, false))
                {
                    vg[i] = true;
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Adds the mesh.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <param name="vg">The vg.</param>
        private void AddMeshNew(Mesh m, ref VoxelGrid3D vg)
        {
            if (Distance < RhinoMath.ZeroTolerance)
            {
                // test in 3 directions.
                var vgX = vg.CloneEmpty();
                var vgY = vg.CloneEmpty();
                var vgZ = vg.CloneEmpty();

                VoxelateMeshInDirection(m, 0, ref vgX);
                VoxelateMeshInDirection(m, 1, ref vgY);
                VoxelateMeshInDirection(m, 2, ref vgZ);
                vgX.And(vgY);
                vgX.And(vgZ);
                vg.Or(vgX);
            }
            else
            {
                // add open mesh
                var bb = m.GetBoundingBox(true);
                bb.Inflate(Distance * 0.6);
                for (var i = 0; i < vg.Count; i++)
                {
                    var isInside = false;
                    var pt       = vg.EvaluatePoint(i);
                    if (bb.Contains(pt))
                    {
                        var foundPoint = m.ClosestPoint(pt);

                        if (foundPoint.DistanceTo(pt) <= Distance)
                        {
                            isInside = true;
                        }
                    }
                    if (isInside)
                    {
                        vg[i] = true;
                    }
                }
            }
        }
Beispiel #7
0
        /// <summary>
        ///   Add a non closed brep by using a distance to the grid
        /// </summary>
        /// <param name="b"></param>
        /// <param name="vg"></param>
        public void AddOpenBrep(Brep b, ref VoxelGrid3D vg)
        {
            var bb = b.GetBoundingBox(false);

            bb.Inflate(Distance * 0.6);
            for (var i = 0; i < vg.Grid.Count; i++)
            {
                var pt = vg.EvaluatePoint(i);
                if (!bb.Contains(pt))
                {
                    continue;
                }

                var cp = b.ClosestPoint(pt);
                AddPt(cp, ref vg);
                if (pt.DistanceTo(cp) < Distance)
                {
                    AddPt(pt, ref vg);
                }
            }
        }
Beispiel #8
0
 /// <summary>
 ///   Add curve that intersects with voxels to the grid
 ///   TODO:
 ///   Improve by dividing the curve?
 ///   Getting more intervals?
 ///   Getting custom distance on the curve?
 /// </summary>
 /// <param name="curve"></param>
 /// <param name="vg"></param>
 public void AddCrv(Curve curve, ref VoxelGrid3D vg)
 {
     // todo: explode curves, and only search in radius of box?
     if (Distance > RhinoMath.ZeroTolerance)
     {
         var bb = curve.GetBoundingBox(true);
         bb.Inflate((vg.VoxelSize.X + Distance) * 2, (vg.VoxelSize.Y + Distance) * 2, (vg.VoxelSize.Z + Distance) * 2);
         var maxDistance =
             Math.Sqrt(Math.Pow(vg.VoxelSize.X, 2) + Math.Pow(vg.VoxelSize.Y, 2) + Math.Pow(vg.VoxelSize.Z, 2));
         for (var i = 0; i < vg.Count; i++)
         {
             var pt = vg.EvaluatePoint(i);
             if (bb.Contains(pt))
             {
                 curve.ClosestPoint(pt, out var t);
                 var cp   = curve.PointAt(t);
                 var dist = cp.DistanceTo(pt);
                 if (Math.Abs(Distance) < RhinoMath.ZeroTolerance && dist <= maxDistance)
                 {
                     AddPt(cp, ref vg);
                 }
                 else if (dist < Distance)
                 {
                     vg[i] = true;
                 }
             }
         }
     }
     else
     {
         var plc = curve.ToPolyline(0, 0, 0.1, 0, 0.5, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance, 0,
                                    vg.VoxelSize.MinimumCoordinate, true);
         plc.TryGetPolyline(out var pl);
         foreach (var item in pl.GetSegments())
         {
             AddLine(item, ref vg);
         }
     }
 }
        /// <summary>
        /// Polygonize grid using the marching cubes algorithm
        /// </summary>
        /// <param name="vg">Voxelgrid</param>
        /// <param name="points">List of points in the voxelgrid</param>
        /// <param name="val">Values (0 or 1 list)</param>
        /// <param name="isolevel">Isolevel at value val (between 0 and 1)</param>
        /// <param name="m">Mesh to add faces to</param>
        /// <param name="cubeindex">Unknown parameter at this point, why was this an out value again?</param>
        /// <returns>The amount of trianges added to the mesh</returns>
        public int Polygonise(VoxelGrid3D vg, Point3i[] points, float[] val, float isolevel, ref Mesh m, out int cubeindex)
        {
            cubeindex = 0;
            if (val[0] < isolevel)
            {
                cubeindex |= 1;
            }
            if (val[1] < isolevel)
            {
                cubeindex |= 2;
            }
            if (val[2] < isolevel)
            {
                cubeindex |= 4;
            }
            if (val[3] < isolevel)
            {
                cubeindex |= 8;
            }
            if (val[4] < isolevel)
            {
                cubeindex |= 16;
            }
            if (val[5] < isolevel)
            {
                cubeindex |= 32;
            }
            if (val[6] < isolevel)
            {
                cubeindex |= 64;
            }
            if (val[7] < isolevel)
            {
                cubeindex |= 128;
            }

            /* Cube is entirely in/out of the surface */
            if (_edgeTable[cubeindex] == 0)
            {
                return(0);
            }
            var vertlist = new Point3d[12];

            /* Find the vertices where the surface intersects the cube */
            if ((_edgeTable[cubeindex] & 1) == 1)
            {
                vertlist[0] =
                    VertexInterp(isolevel, points[0], points[1], val[0], val[1]);
            }
            if ((_edgeTable[cubeindex] & 2) == 2)
            {
                vertlist[1] =
                    VertexInterp(isolevel, points[1], points[2], val[1], val[2]);
            }
            if ((_edgeTable[cubeindex] & 4) == 4)
            {
                vertlist[2] =
                    VertexInterp(isolevel, points[2], points[3], val[2], val[3]);
            }
            if ((_edgeTable[cubeindex] & 8) == 8)
            {
                vertlist[3] =
                    VertexInterp(isolevel, points[3], points[0], val[3], val[0]);
            }
            if ((_edgeTable[cubeindex] & 16) == 16)
            {
                vertlist[4] =
                    VertexInterp(isolevel, points[4], points[5], val[4], val[5]);
            }
            if ((_edgeTable[cubeindex] & 32) == 32)
            {
                vertlist[5] =
                    VertexInterp(isolevel, points[5], points[6], val[5], val[6]);
            }
            if ((_edgeTable[cubeindex] & 64) == 64)
            {
                vertlist[6] =
                    VertexInterp(isolevel, points[6], points[7], val[6], val[7]);
            }
            if ((_edgeTable[cubeindex] & 128) == 128)
            {
                vertlist[7] =
                    VertexInterp(isolevel, points[7], points[4], val[7], val[4]);
            }
            if ((_edgeTable[cubeindex] & 256) == 256)
            {
                vertlist[8] =
                    VertexInterp(isolevel, points[0], points[4], val[0], val[4]);
            }
            if ((_edgeTable[cubeindex] & 512) == 512)
            {
                vertlist[9] =
                    VertexInterp(isolevel, points[1], points[5], val[1], val[5]);
            }
            if ((_edgeTable[cubeindex] & 1024) == 1024)
            {
                vertlist[10] =
                    VertexInterp(isolevel, points[2], points[6], val[2], val[6]);
            }
            if ((_edgeTable[cubeindex] & 2048) == 2048)
            {
                vertlist[11] =
                    VertexInterp(isolevel, points[3], points[7], val[3], val[7]);
            }
            // evaluate all points between these 8 vertices


            /* Create the triangle */
            var vertexCount = m.Vertices.Count;
            var triangles   = 0;

            for (var k = 0; _triTable[cubeindex, k] != -1; k += 3)
            {
                var facePts = new Point3d[3];
                facePts[0] = vg.EvaluatePoint(vertlist[_triTable[cubeindex, k]]);
                facePts[1] = vg.EvaluatePoint(vertlist[_triTable[cubeindex, k + 1]]);
                facePts[2] = vg.EvaluatePoint(vertlist[_triTable[cubeindex, k + 2]]);
                m.Vertices.AddVertices(facePts);
                // perhaps this should be switched around for the right normal direction
                m.Faces.AddFace(vertexCount, vertexCount + 1, vertexCount + 2);
                vertexCount += 3;
                triangles++;
            }
            return(triangles);
        }
Beispiel #10
0
        private void VoxelateMeshInDirection(Mesh m, int dir, ref VoxelGrid3D vg)
        {
            var box = new Box(vg.Plane, vg.BBox.ToBrep());

            box.Inflate(box.X.Length * 0.1, box.Y.Length * 0.1, box.Z.Length * 0.1);
            Plane min;
            Plane max;
            int   dirA;
            int   dirB;

            switch (dir)
            {
            case 0:
            {
                dirA = 1;
                dirB = 2;
                min  = new Plane(box.PointAt(0, 0, 0), vg.Plane.XAxis);
                max  = new Plane(box.PointAt(1, 0, 0), vg.Plane.XAxis);
                break;
            }

            case 1:
            {
                dirA = 0;
                dirB = 2;
                min  = new Plane(box.PointAt(0, 0, 0), vg.Plane.YAxis);
                max  = new Plane(box.PointAt(0, 1, 0), vg.Plane.YAxis);
                break;
            }

            case 2:
            {
                dirA = 0;
                dirB = 1;
                min  = new Plane(box.PointAt(0, 0, 0), vg.Plane.ZAxis);
                max  = new Plane(box.PointAt(0, 0, 1), vg.Plane.ZAxis);
                break;
            }

            default:
                throw new Exception("Invalid direction");
            }

            for (var a = 0; a < vg.SizeUVW[dirA]; a++)
            {
                for (var b = 0; b < vg.SizeUVW[dirB]; b++)
                {
                    var idx = new Point3i {
                        [dirA] = a, [dirB] = b
                    };
                    var pt    = vg.EvaluatePoint(idx);
                    var ptMin = min.ClosestPoint(pt);
                    var ptMax = max.ClosestPoint(pt);
                    var line  = new Line(ptMin, ptMax);
                    var pts   = Intersection.MeshLine(m, new Line(ptMin, ptMax), out _);
                    // sort by line direction, the points should be in the same order as the line.
                    pts = pts.OrderBy(intPt => line.ClosestParameter(intPt)).ToArray();
                    for (var i = 0; i < pts.Length - 1; i += 2)
                    {
                        AddLine(new Line(pts[i], pts[i + 1]), ref vg);
                    }
                }
            }
        }