コード例 #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);
                        }
                    }
                }
            }
        }
コード例 #2
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;
             }
         }
     }
 }
コード例 #3
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]);
        }
コード例 #4
0
        /// <summary>
        /// Converts a voxelgrid to a mesh hull.
        /// TODO: Add hashmap vertex id  > pixel/pixelface; to compute the pixel to which the mesh belongs.
        /// </summary>
        /// <param name="vg"></param>
        /// <returns></returns>
        public static Mesh VoxelGridToMesh(VoxelGrid3D vg)
        {
            Vector3d[] FaceDirections;
            Vector3d[] AxisDirections;
            Point3i[]  RelativePosition;
            int[,] FaceAxis;
            double[] FaceSizes;

            FaceDirections = new Vector3d[6] {
                vg.BBox.Plane.XAxis, -vg.BBox.Plane.XAxis, vg.BBox.Plane.YAxis, -vg.BBox.Plane.YAxis, vg.BBox.Plane.ZAxis, -vg.BBox.Plane.ZAxis
            };
            AxisDirections = new Vector3d[3] {
                vg.BBox.Plane.XAxis, vg.BBox.Plane.YAxis, vg.BBox.Plane.ZAxis
            };
            // the different faces
            RelativePosition = new Point3i[6] {
                new Point3i(1, 0, 0), new Point3i(-1, 0, 0), new Point3i(0, 1, 0), new Point3i(0, -1, 0), new Point3i(0, 0, 1), new Point3i(0, 0, -1)
            };

            FaceAxis = new int[3, 2] {
                { 1, 2 },
                { 2, 0 },
                { 0, 1 }
            };

            // the sizes of the faces
            FaceSizes = new double[3] {
                vg.SizeUVW.X, vg.SizeUVW.Y, vg.SizeUVW.Z
            };

            var m = new Mesh();

            for (var i = 0; i < vg.Count; i++)
            {
                if (vg[i] == false)
                {
                    continue;
                }

                for (var faceId = 0; faceId < 6; faceId++)
                {
                    if (vg.GetRelativePointValue(i, RelativePosition[faceId]) != 1)
                    {
                        AddFacadeToMesh(vg, i, faceId, ref m, FaceDirections, AxisDirections, FaceAxis);
                    }
                }
            }
            //m.Vertices.CombineIdentical(false, true);
            m.Normals.ComputeNormals();
            m.Compact();
            return(m);
        }
コード例 #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;
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Add a line in world coordinates to a voxelgrid
        /// </summary>
        /// <param name="line"></param>
        /// <param name="vg"></param>
        private void AddLine(Line line, ref VoxelGrid3D vg)
        {
            var start = vg.ClosestPoint(line.From);
            var end   = vg.ClosestPoint(line.To);

            foreach (var pt in InterateLine(start, end))
            {
                if (pt < Point3i.Origin || pt >= vg.SizeUVW)
                {
                    continue;
                }
                vg[pt] = true;
            }
        }
コード例 #7
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;
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        ///   Add a brep to the voxelgrid
        /// </summary>
        /// <param name="b"></param>
        /// <param name="vg"></param>
        public void AddBrep(Brep b, ref VoxelGrid3D vg)
        {
            if (b == null || b.Equals(default(Brep)) || !b.IsValid)
            {
                return;
            }

            if (!b.IsSolid || Distance > RhinoMath.ZeroTolerance)
            {
                AddOpenBrep(b, ref vg);
            }
            else
            {
                AddSolidBrep(b, ref vg);
            }
        }
コード例 #9
0
ファイル: ByteHelper.cs プロジェクト: arendvw/voxeltools
        /// <summary>
        /// Convert a voxelgrid to a bytearray
        /// </summary>
        /// <param name="vg"></param>
        /// <returns></returns>
        public static byte[] ToByte(VoxelGrid3D vg)
        {
            // check for integer overflows
            checked {
                var byteGrid   = ToByte(vg.Grid);
                var byteLength = 120 + 24 + 4 + byteGrid.Length;

                var output = new byte[byteLength];
                // voxelsize can be float = 9 bytes
                ToByte(vg.VoxelSize).CopyTo(output, 0);
                // bbox can be ptA, ptB + plane equation. 3x3x2 = 18
                // plane equation = normalize plane. Take a plane and take the origin out of the equation
                // plane equation -
                ToByte(vg.BBox).CopyTo(output, 24);
                ToByte(vg.Grid).CopyTo(output, 144);
                return(output);
            }
        }
コード例 #10
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;
                    }
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var    bb = new Box();
            double x, y, z;

            x = y = z = 0;
            DA.GetData(1, ref x);
            DA.GetData(2, ref y);
            DA.GetData(3, ref z);
            DA.GetData(0, ref bb);

            var vg = new VoxelGrid3D(bb, new Point3d(x, y, z));

            if (!vg.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Result was an invalid grid");
            }

            DA.SetData(0, (VoxelGrid3D)vg.Clone());
            AddRenderGrid(vg);
        }
コード例 #12
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);
                }
            }
        }
コード例 #13
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);
         }
     }
 }
コード例 #14
0
        private static void LimitGrid(ref VoxelGrid3D vg, int i)
        {
            // limit, start with Z size.
            var trueCount = vg.CountNonZero;

            for (var z = vg.SizeUVW.Z - 1; z >= 0; z--)
            {
                for (var y = 0; y < vg.SizeUVW.Y; y++)
                {
                    for (var x = 0; x < vg.SizeUVW.X; x++)
                    {
                        if (vg[new Point3i(x, y, z)])
                        {
                            vg[new Point3i(x, y, z)] = false;
                            trueCount--;
                        }
                        if (trueCount == i)
                        {
                            return;
                        }
                    }
                }
            }
        }
コード例 #15
0
        /// <summary>
        /// Add voxels to the grid building up from the bottom to the top.
        /// </summary>
        /// <param name="vg">VoxelGrid</param>
        /// <param name="count">Amount of voxels to be added.</param>
        private void IncreaseGridFromBottom(ref VoxelGrid3D vg, int count)
        {
            var trueIncCount = vg.CountNonZero;

            for (var z = 0; z < vg.SizeUVW.Z; z++)
            {
                for (var y = 0; y < vg.SizeUVW.Y; y++)
                {
                    for (var x = 0; x < vg.SizeUVW.X; x++)
                    {
                        var pt = new Point3i(x, y, z);
                        if (vg[pt] == false)
                        {
                            vg[pt] = true;
                            trueIncCount++;
                            if (trueIncCount == count)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
コード例 #16
0
 /// <summary>
 /// Add a grid to the render queue
 /// </summary>
 /// <param name="grid">The grid.</param>
 public void AddRenderGrid(VoxelGrid3D grid)
 {
     RenderGrid.Add(grid);
     RenderBb.Union(grid.BBox.BoundingBox);
     GenerateBoxGrid(grid);
 }
コード例 #17
0
        /// <summary>
        /// Gets the voxelgrid mesh by plane
        /// Return a seperate list for each face direction
        /// </summary>
        /// <param name="vg"></param>
        /// <returns></returns>
        public static List <Mesh> VoxelGridToMeshByPlanes(VoxelGrid3D vg)
        {
            Vector3d[] FaceDirections;
            Vector3d[] AxisDirections;
            Point3i[]  RelativePosition;
            int[,] FaceAxis;
            double[] FaceSizes;
            var      Meshes = new List <Mesh>();

            for (var i = 0; i < 6; i++)
            {
                Meshes.Add(new Mesh());
            }


            FaceDirections = new Vector3d[6] {
                vg.BBox.Plane.XAxis, -vg.BBox.Plane.XAxis, vg.BBox.Plane.YAxis, -vg.BBox.Plane.YAxis, vg.BBox.Plane.ZAxis, -vg.BBox.Plane.ZAxis
            };
            AxisDirections = new Vector3d[3] {
                vg.BBox.Plane.XAxis, vg.BBox.Plane.YAxis, vg.BBox.Plane.ZAxis
            };
            // the different faces
            RelativePosition = new Point3i[6] {
                new Point3i(1, 0, 0), new Point3i(-1, 0, 0), new Point3i(0, 1, 0), new Point3i(0, -1, 0), new Point3i(0, 0, 1), new Point3i(0, 0, -1)
            };

            FaceAxis = new int[3, 2] {
                { 1, 2 },
                { 2, 0 },
                { 0, 1 }
            };

            // the sizes of the faces
            FaceSizes = new double[3] {
                vg.SizeUVW.X, vg.SizeUVW.Y, vg.SizeUVW.Z
            };

            for (var i = 0; i < vg.Count; i++)
            {
                if (vg[i] == false)
                {
                    continue;
                }
                for (var faceId = 0; faceId < 6; faceId++)
                {
                    var m = Meshes[faceId];
                    if (vg.GetRelativePointValue(i, RelativePosition[faceId]) != 1)
                    {
                        try
                        {
                            AddFacadeToMesh(vg, i, faceId, ref m, FaceDirections, AxisDirections, FaceAxis);
                        }
                        catch (Exception e)
                        {
                            throw new Exception(
                                      $"Adding Facade {faceId} of Voxel {i} to Mesh failed: {e.ToString()}");
                        }
                    }
                }
            }
            //m.Vertices.CombineIdentical(false, true);
            for (var i = 0; i < 6; i++)
            {
                Meshes[i].Normals.ComputeNormals();
                Meshes[i].Compact();
            }
            return(Meshes);
        }
コード例 #18
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);
                    }
                }
            }
        }
コード例 #19
0
        private void IncreaseGrid(ref VoxelGrid3D vg, int count)
        {
            var trueCount         = vg.CountNonZero;
            var possibleLocations = new List <int>();
            var foundRoof         = false;

            for (var z = vg.SizeUVW.Z - 1; z >= 0; z--)
            {
                if (foundRoof)
                {
                    break;
                }

                for (var y = 0; y < vg.SizeUVW.Y; y++)
                {
                    for (var x = 0; x < vg.SizeUVW.X; x++)
                    {
                        var pt = new Point3i(x, y, z);
                        if (vg[pt] != true)
                        {
                            continue;
                        }
                        foundRoof = true;
                        possibleLocations.Add(Point3i.PointUvwToIndex(vg.SizeUVW, pt));
                    }
                }
            }

            // location division
            // goal-current
            // difference: the first x voxels get extra.
            // then add x voxels to each location.

            var difference = count - trueCount;
            var height     = Convert.ToInt32(Math.Floor((double)difference / possibleLocations.Count));
            var rest       = difference % possibleLocations.Count;

            for (var i = 0; i < possibleLocations.Count; i++)
            {
                var makeheight = height;
                if (rest > 0)
                {
                    makeheight += 1;
                    rest--;
                }

                for (var j = 1; j <= makeheight; j++)
                {
                    var pt       = new Point3i(0, 0, j);
                    var position = Point3i.IndexToPointUvw(vg.SizeUVW, possibleLocations[i]) + pt;
                    vg[position] = true;
                }
            }

            if (vg.CountNonZero != count)
            {
                // the grid is empty / reaches to the roof.
                // add from the bottom.
                IncreaseGridFromBottom(ref vg, count);
            }
        }
コード例 #20
0
        /// <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);
        }
コード例 #21
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var vg = default(VoxelGrid3D);

            DA.GetData(0, ref vg);

            var isRoof          = new VoxelGrid3D(vg.BBox, vg.VoxelSize);
            var hasAccessible   = new VoxelGrid3D(vg.BBox, vg.VoxelSize);
            var accessViaStairs = new VoxelGrid3D(vg.BBox, vg.VoxelSize);

            var tr = new Point3i(0, 0, 1);
            var t1 = new Point3i(0, 1, 1);
            var t2 = new Point3i(1, 0, 1);
            var t3 = new Point3i(-1, 0, 1);
            var t4 = new Point3i(0, -1, 1);

            for (var i = 0; i < vg.Count; i++)
            {
                if (vg[i] == false)
                {
                    continue;
                }
                // there's nothing above us.. only sky
                if (vg.GetRelativePointValue(i, tr) == 0)
                {
                    var accessible = false;
                    if (vg.GetRelativePointValue(i, t1) == 1)
                    {
                        accessible = true;
                        hasAccessible.SetRelativePointValue(i, t1, true);
                    }
                    if (vg.GetRelativePointValue(i, t2) == 1)
                    {
                        accessible = true;
                        hasAccessible.SetRelativePointValue(i, t2, true);
                    }
                    if (vg.GetRelativePointValue(i, t3) == 1)
                    {
                        accessible = true;
                        hasAccessible.SetRelativePointValue(i, t3, true);
                    }
                    if (vg.GetRelativePointValue(i, t4) == 1)
                    {
                        accessible = true;
                        hasAccessible.SetRelativePointValue(i, t4, true);
                    }

                    if (accessible)
                    {
                        isRoof[i] = true;
                    }
                    else
                    {
                        accessViaStairs[i] = true;
                    }
                }
            }

            DA.SetData(0, hasAccessible);
            DA.SetData(1, isRoof);
            DA.SetData(2, accessViaStairs);
        }