/// <summary> /// Add a mesh to the scalar grid /// </summary> /// <param name="m">Volumetric mesh</param> /// <param name="exp">Falloff Exponent</param> /// <param name="mass">Mass m</param> /// <param name="sg">Scalar grid</param> private void AddMesh(Mesh m, double exp, double mass, ref ScalarGrid3D sg) { if (m.IsClosed) { // add closed mesh var bb = m.GetBoundingBox(true); var length = bb.Diagonal.Length * 1.1; for (var i = 0; i < sg.Count; i++) { var pt = sg.EvaluatePoint(i); var isInside = false; Intersection.MeshLine(m, new Line(pt, Vector3d.XAxis, length), out var faces); if (faces != null) { isInside = faces.Length % 2 == 1; } var cp = m.ClosestPoint(pt); sg[i] += CalculateMass(cp.DistanceTo(pt), mass, exp, isInside); } } else { // add open mesh for (var i = 0; i < sg.Count; i++) { var pt = sg.EvaluatePoint(i); var foundPoint = m.ClosestPoint(pt); var dist = foundPoint.DistanceTo(pt); sg[i] += CalculateMass(dist, mass, exp, false); } } }
/// <summary> /// Add a point to the scalar grid. Currently an expensive operation /// </summary> /// <param name="pt"></param> /// <param name="exp"></param> /// <param name="mass"></param> /// <param name="vg"></param> public void AddPt(Point3d pt, double exp, double mass, ref ScalarGrid3D vg) { for (var i = 0; i < vg.Count; i++) { var dist = vg.EvaluatePoint(i).DistanceTo(pt); vg[i] += CalculateMass(dist, mass, exp); } // }
/// <summary> /// Add an open brep (non inside detection) /// </summary> /// <param name="b"></param> /// <param name="exp"></param> /// <param name="mass"></param> /// <param name="vg"></param> public void AddOpenBrep(Brep b, double exp, double mass, ref ScalarGrid3D vg) { for (var i = 0; i < vg.Count; i++) { var pt = vg.EvaluatePoint(i); var cp = b.ClosestPoint(pt); var dist = pt.DistanceTo(cp); vg[i] += CalculateMass(dist, mass, exp); } }
/// <summary> /// Add a solid brep /// </summary> /// <param name="b"></param> /// <param name="exp"></param> /// <param name="mass"></param> /// <param name="vg"></param> public void AddSolidBrep(Brep b, double exp, double mass, ref ScalarGrid3D 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(b, 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 isInside = false; var pti = new Point3i(x, y, z); var pt = vg.EvaluatePoint(pti); var distance = b.ClosestPoint(pt).DistanceTo(pt); for (var i = 0; i < surfaces.Length; i++) { //BoundingBox bb = surfaces[i].GetBoundingBox(false); if (surfaces[i].ClosestPoint(pt).DistanceTo(pt) < DocumentHelper.GetModelTolerance()) { isInside = true; break; } } vg[pti] = +CalculateMass(distance, mass, exp, isInside); } } } }
/// <summary> /// Add a curve to the scalar grid /// </summary> /// <param name="curve"></param> /// <param name="exp"></param> /// <param name="mass"></param> /// <param name="sg"></param> public void AddCrv(Curve curve, double exp, double mass, ref ScalarGrid3D sg) { var bb = curve.GetBoundingBox(true); bb.Inflate(sg.VoxelSize.X * 2, sg.VoxelSize.Y * 2, sg.VoxelSize.Z * 2); var maxDistance = Math.Sqrt(Math.Pow(sg.VoxelSize.X, 2) + Math.Pow(sg.VoxelSize.Y, 2) + Math.Pow(sg.VoxelSize.Z, 2)); for (var i = 0; i < sg.Count; i++) { var pt = sg.EvaluatePoint(i); curve.ClosestPoint(pt, out var t); var cp = curve.PointAt(t); var dist = cp.DistanceTo(pt); sg[i] += CalculateMass(dist, mass, exp); } }
/// <summary> /// Add a box to the scalar grid /// </summary> /// <param name="oBox"></param> /// <param name="exp"></param> /// <param name="mass"></param> /// <param name="sg"></param> private void AddBox(Box oBox, double exp, double mass, ref ScalarGrid3D sg) { for (var i = 0; i < sg.Count; i++) { var pt = sg.EvaluatePoint(i); var contains = oBox.Contains(pt, false); var cp = oBox.ClosestPoint(pt); var distance = pt.DistanceTo(cp); if (contains) { distance *= -1; } sg[i] = +CalculateMass(Convert.ToSingle(distance), mass, exp); } }
/// <summary> /// Marching cubes algorithm /// </summary> /// <param name="vg"></param> /// <param name="points"></param> /// <param name="val"></param> /// <param name="isolevel"></param> /// <param name="m"></param> /// <param name="cubeindex"></param> /// <returns></returns> public int Polygonise(ScalarGrid3D 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 var z = m.Vertices.Count; /* 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); }