public void AddTriangleToBuffer (g3.Triangle3d _triangle, XYZ _normal, ColorWithTransparency _cwt, XYZ _offset, bool _transparent) { var transBuffer = this.TransTriangleBuffer; var nonTransBuffer = this.NonTransTriangleBuffer; TriangleInfo triangleInfo = new TriangleInfo(_triangle, _normal, _cwt, _offset); if (_transparent) { transBuffer.Triangles.Add(triangleInfo); transBuffer.VertexBufferCount += 3; transBuffer.PrimitiveCount += 1; } else { nonTransBuffer.Triangles.Add(triangleInfo); nonTransBuffer.VertexBufferCount += 3; nonTransBuffer.PrimitiveCount += 1; } }
public static AxisAlignedBox3d Bounds(ref Triangle3d tri) { return(Bounds(ref tri.V0, ref tri.V1, ref tri.V2)); }
void find_hit_triangle(int iBox, ref Ray3d ray, ref double fNearestT, ref int tID) { int idx = box_to_index[iBox]; if (idx < triangles_end) // triange-list case, array is [N t1 t2 ... tN] { Triangle3d tri = new Triangle3d(); int num_tris = index_list[idx]; for (int i = 1; i <= num_tris; ++i) { int ti = index_list[idx + i]; // [TODO] optimize this mesh.GetTriVertices(ti, ref tri.V0, ref tri.V1, ref tri.V2); IntrRay3Triangle3 ray_tri_hit = new IntrRay3Triangle3(ray, tri); if (ray_tri_hit.Find()) { if (ray_tri_hit.RayParameter < fNearestT) { fNearestT = ray_tri_hit.RayParameter; tID = ti; } } } } else // internal node, either 1 or 2 child boxes { double e = MathUtil.ZeroTolerancef; int iChild1 = index_list[idx]; if (iChild1 < 0) // 1 child, descend if nearer than cur min-dist { iChild1 = (-iChild1) - 1; double fChild1T = box_ray_intersect_t(iChild1, ray); if (fChild1T <= fNearestT + e) { find_hit_triangle(iChild1, ref ray, ref fNearestT, ref tID); } } else // 2 children, descend closest first { iChild1 = iChild1 - 1; int iChild2 = index_list[idx + 1] - 1; double fChild1T = box_ray_intersect_t(iChild1, ray); double fChild2T = box_ray_intersect_t(iChild2, ray); if (fChild1T < fChild2T) { if (fChild1T <= fNearestT + e) { find_hit_triangle(iChild1, ref ray, ref fNearestT, ref tID); if (fChild2T <= fNearestT + e) { find_hit_triangle(iChild2, ref ray, ref fNearestT, ref tID); } } } else { if (fChild2T <= fNearestT + e) { find_hit_triangle(iChild2, ref ray, ref fNearestT, ref tID); if (fChild1T <= fNearestT + e) { find_hit_triangle(iChild1, ref ray, ref fNearestT, ref tID); } } } } } }
// Create and populate a pair of vertex and index buffers. Also update parameters associated with the format of the vertices. private void ProcessTriangles(RenderingPassBufferStorage bufferStorage) { List <TriangleInfo> triangles = bufferStorage.Triangles; if (triangles.Count == 0) { return; } bool useNormals = this.Inputs.EnableFaceNormal; // Vertex attributes are stored sequentially in vertex buffers. The attributes can include position, normal vector, and color. // All vertices within a vertex buffer must have the same format. Possible formats are enumerated by VertexFormatBits. // Vertex format also determines the type of rendering effect that can be used with the vertex buffer. In this sample, // the color is always encoded in the vertex attributes. bufferStorage.FormatBits = useNormals ? VertexFormatBits.PositionNormalColored : VertexFormatBits.PositionColored; // The format of the vertices determines the size of the vertex buffer. int vertexBufferSizeInFloats = (useNormals ? VertexPositionNormalColored.GetSizeInFloats() : VertexPositionColored.GetSizeInFloats()) * bufferStorage.VertexBufferCount; bufferStorage.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(vertexBufferSizeInFloats); int numTriangles = triangles.Count; if (useNormals) { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionNormalColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionNormalColored(); for (int i = 0; i < numTriangles; i++) { var triangleInfo = triangles[i]; g3.Triangle3d triangle = triangleInfo.Triangle; vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V0.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V1.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V2.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); } } else { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionColored(); for (int i = 0; i < numTriangles; i++) { var triangleInfo = triangles[i]; g3.Triangle3d triangle = triangleInfo.Triangle; // make the color of all faces white in HLR ColorWithTransparency color = triangleInfo.ColorWithTransparency; vertexStream.AddVertex(new VertexPositionColored(triangle.V0.ToXYZ() + triangleInfo.Offset, color)); vertexStream.AddVertex(new VertexPositionColored(triangle.V1.ToXYZ() + triangleInfo.Offset, color)); vertexStream.AddVertex(new VertexPositionColored(triangle.V2.ToXYZ() + triangleInfo.Offset, color)); } } bufferStorage.VertexBuffer.Unmap(); // Primitives are specified using a pair of vertex and index buffers. An index buffer contains a sequence of indices into // the associated vertex buffer, each index referencing a particular vertex. bufferStorage.IndexBufferCount = bufferStorage.PrimitiveCount * IndexTriangle.GetSizeInShortInts(); int indexBufferSizeInShortInts = 1 * bufferStorage.IndexBufferCount; bufferStorage.IndexBuffer = new IndexBuffer(indexBufferSizeInShortInts); bufferStorage.IndexBuffer.Map(indexBufferSizeInShortInts); // An IndexStream is used to write data into an IndexBuffer. IndexStreamTriangle indexStream = bufferStorage.IndexBuffer.GetIndexStreamTriangle(); int currIndex = 0; for (int i = 0; i < numTriangles; i++) { // Add three indices that define a triangle. indexStream.AddTriangle(new IndexTriangle(currIndex + 0, currIndex + 1, currIndex + 2)); currIndex += 3; } bufferStorage.IndexBuffer.Unmap(); // VertexFormat is a specification of the data that is associated with a vertex (e.g., position). bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); // Effect instance is a specification of the appearance of geometry. For example, it may be used to specify color, if there is no color information provided with the vertices. bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); }
public DistSegment3Triangle3(Segment3d SegmentIn, Triangle3d TriangleIn) { this.triangle = TriangleIn; this.segment = SegmentIn; }
bool GetCoplanarIntersection(ref Plane3d plane, ref Triangle3d tri0, ref Triangle3d tri1) { // Project triangles onto coordinate plane most aligned with plane // normal. int maxNormal = 0; double fmax = Math.Abs(plane.Normal.x); double absMax = Math.Abs(plane.Normal.y); if (absMax > fmax) { maxNormal = 1; fmax = absMax; } absMax = Math.Abs(plane.Normal.z); if (absMax > fmax) { maxNormal = 2; } Triangle2d projTri0 = new Triangle2d(), projTri1 = new Triangle2d(); int i; if (maxNormal == 0) { // Project onto yz-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].yz; projTri1[i] = tri1[i].yz; } } else if (maxNormal == 1) { // Project onto xz-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].xz; projTri1[i] = tri1[i].xz; } } else { // Project onto xy-plane. for (i = 0; i < 3; ++i) { projTri0[i] = tri0[i].xy; projTri1[i] = tri1[i].xy; } } // 2D triangle intersection routines require counterclockwise ordering. Vector2d save; Vector2d edge0 = projTri0[1] - projTri0[0]; Vector2d edge1 = projTri0[2] - projTri0[0]; if (edge0.DotPerp(edge1) < (double)0) { // Triangle is clockwise, reorder it. save = projTri0[1]; projTri0[1] = projTri0[2]; projTri0[2] = save; } edge0 = projTri1[1] - projTri1[0]; edge1 = projTri1[2] - projTri1[0]; if (edge0.DotPerp(edge1) < (double)0) { // Triangle is clockwise, reorder it. save = projTri1[1]; projTri1[1] = projTri1[2]; projTri1[2] = save; } IntrTriangle2Triangle2 intr = new IntrTriangle2Triangle2(projTri0, projTri1); if (!intr.Find()) { return(false); } PolygonPoints = new Vector3d[intr.Quantity]; // Map 2D intersections back to the 3D triangle space. Quantity = intr.Quantity; if (maxNormal == 0) { double invNX = ((double)1) / plane.Normal.x; for (i = 0; i < Quantity; i++) { double y = intr.Points[i].x; double z = intr.Points[i].y; double x = invNX * (plane.Constant - plane.Normal.y * y - plane.Normal.z * z); PolygonPoints[i] = new Vector3d(x, y, z); } } else if (maxNormal == 1) { double invNY = ((double)1) / plane.Normal.y; for (i = 0; i < Quantity; i++) { double x = intr.Points[i].x; double z = intr.Points[i].y; double y = invNY * (plane.Constant - plane.Normal.x * x - plane.Normal.z * z); PolygonPoints[i] = new Vector3d(x, y, z); } } else { double invNZ = ((double)1) / plane.Normal.z; for (i = 0; i < Quantity; i++) { double x = intr.Points[i].x; double y = intr.Points[i].y; double z = invNZ * (plane.Constant - plane.Normal.x * x - plane.Normal.y * y); PolygonPoints[i] = new Vector3d(x, y, z); } } Result = IntersectionResult.Intersects; Type = IntersectionType.Polygon; return(true); }
public IntrTriangle3Triangle3(Triangle3d t0, Triangle3d t1) { triangle0 = t0; triangle1 = t1; }
/// <summary> /// 1) Find intersection segments /// 2) sort onto existing input mesh vtx/edge/face /// </summary> void find_segments() { var SegVtxMap = new Dictionary <Vector3d, SegmentVtx>(); // find intersection segments // TODO: intersection polygons // TODO: do we need to care about intersection vertices? var targetSpatial = new DMeshAABBTree3(Target, true); var cutSpatial = new DMeshAABBTree3(CutMesh, true); var intersections = targetSpatial.FindAllIntersections(cutSpatial); // for each segment, for each vtx, determine if it is // at an existing vertex, on-edge, or in-face Segments = new IntersectSegment[intersections.Segments.Count]; for (int i = 0; i < Segments.Length; ++i) { var isect = intersections.Segments[i]; var points = new Vector3dTuple2(isect.point0, isect.point1); var iseg = new IntersectSegment() { base_tid = isect.t0 }; Segments[i] = iseg; for (int j = 0; j < 2; ++j) { Vector3d v = points[j]; // if this exact vtx coord has been seen, use same vtx SegmentVtx sv; if (SegVtxMap.TryGetValue(v, out sv)) { iseg[j] = sv; continue; } sv = new SegmentVtx() { v = v }; SegVertices.Add(sv); SegVtxMap[v] = sv; iseg[j] = sv; // this vtx is tol-equal to input mesh vtx int existing_v = find_existing_vertex(isect.point0); if (existing_v >= 0) { sv.initial_type = sv.type = 0; sv.elem_id = existing_v; sv.vtx_id = existing_v; VIDToSegVtxMap[sv.vtx_id] = sv; continue; } var tri = new Triangle3d(); Target.GetTriVertices(isect.t0, ref tri.V0, ref tri.V1, ref tri.V2); Index3i tv = Target.GetTriangle(isect.t0); // this vtx is tol-on input mesh edge int on_edge_i = on_edge(ref tri, ref v); if (on_edge_i >= 0) { sv.initial_type = sv.type = 1; sv.elem_id = Target.FindEdge(tv[on_edge_i], tv[(on_edge_i + 1) % 3]); Util.gDevAssert(sv.elem_id != DMesh3.InvalidID); add_edge_vtx(sv.elem_id, sv); continue; } // otherwise contained in input mesh face sv.initial_type = sv.type = 2; sv.elem_id = isect.t0; add_face_vtx(sv.elem_id, sv); } } }
public static bool Intersects(ref Triangle3d triangle0, ref Triangle3d triangle1) { IntersectionType dummy = 0; return(Intersects(ref triangle0, ref triangle1, ref dummy)); }
public IntrRay3Triangle3(Ray3d r, Triangle3d t) { ray = r; triangle = t; }
public static double DistanceSqr(ref Vector3d point, ref Triangle3d triangle, out Vector3d closestPoint, out Vector3d baryCoords) { Vector3d diff = triangle.V0 - point; Vector3d edge0 = triangle.V1 - triangle.V0; Vector3d edge1 = triangle.V2 - triangle.V0; double a00 = edge0.LengthSquared; double a01 = edge0.Dot(ref edge1); double a11 = edge1.LengthSquared; double b0 = diff.Dot(ref edge0); double b1 = diff.Dot(ref edge1); double c = diff.LengthSquared; double det = Math.Abs(a00 * a11 - a01 * a01); double s = a01 * b1 - a11 * b0; double t = a01 * b0 - a00 * b1; double sqrDistance; if (s + t <= det) { if (s < 0) { if (t < 0) // region 4 { if (b0 < 0) { t = 0; if (-b0 >= a00) { s = 1; sqrDistance = a00 + (2) * b0 + c; } else { s = -b0 / a00; sqrDistance = b0 * s + c; } } else { s = 0; if (b1 >= 0) { t = 0; sqrDistance = c; } else if (-b1 >= a11) { t = 1; sqrDistance = a11 + (2) * b1 + c; } else { t = -b1 / a11; sqrDistance = b1 * t + c; } } } else // region 3 { s = 0; if (b1 >= 0) { t = 0; sqrDistance = c; } else if (-b1 >= a11) { t = 1; sqrDistance = a11 + (2) * b1 + c; } else { t = -b1 / a11; sqrDistance = b1 * t + c; } } } else if (t < 0) // region 5 { t = 0; if (b0 >= 0) { s = 0; sqrDistance = c; } else if (-b0 >= a00) { s = 1; sqrDistance = a00 + (2) * b0 + c; } else { s = -b0 / a00; sqrDistance = b0 * s + c; } } else // region 0 { // minimum at interior point double invDet = (1) / det; s *= invDet; t *= invDet; sqrDistance = s * (a00 * s + a01 * t + (2) * b0) + t * (a01 * s + a11 * t + (2) * b1) + c; } } else { double tmp0, tmp1, numer, denom; if (s < 0) // region 2 { tmp0 = a01 + b0; tmp1 = a11 + b1; if (tmp1 > tmp0) { numer = tmp1 - tmp0; denom = a00 - (2) * a01 + a11; if (numer >= denom) { s = 1; t = 0; sqrDistance = a00 + (2) * b0 + c; } else { s = numer / denom; t = 1 - s; sqrDistance = s * (a00 * s + a01 * t + (2) * b0) + t * (a01 * s + a11 * t + (2) * b1) + c; } } else { s = 0; if (tmp1 <= 0) { t = 1; sqrDistance = a11 + (2) * b1 + c; } else if (b1 >= 0) { t = 0; sqrDistance = c; } else { t = -b1 / a11; sqrDistance = b1 * t + c; } } } else if (t < 0) // region 6 { tmp0 = a01 + b1; tmp1 = a00 + b0; if (tmp1 > tmp0) { numer = tmp1 - tmp0; denom = a00 - (2) * a01 + a11; if (numer >= denom) { t = 1; s = 0; sqrDistance = a11 + (2) * b1 + c; } else { t = numer / denom; s = 1 - t; sqrDistance = s * (a00 * s + a01 * t + (2) * b0) + t * (a01 * s + a11 * t + (2) * b1) + c; } } else { t = 0; if (tmp1 <= 0) { s = 1; sqrDistance = a00 + (2) * b0 + c; } else if (b0 >= 0) { s = 0; sqrDistance = c; } else { s = -b0 / a00; sqrDistance = b0 * s + c; } } } else // region 1 { numer = a11 + b1 - a01 - b0; if (numer <= 0) { s = 0; t = 1; sqrDistance = a11 + (2) * b1 + c; } else { denom = a00 - (2) * a01 + a11; if (numer >= denom) { s = 1; t = 0; sqrDistance = a00 + (2) * b0 + c; } else { s = numer / denom; t = 1 - s; sqrDistance = s * (a00 * s + a01 * t + (2) * b0) + t * (a01 * s + a11 * t + (2) * b1) + c; } } } } closestPoint = triangle.V0 + s * edge0 + t * edge1; baryCoords = new Vector3d(1 - s - t, s, t); // Account for numerical round-off error. return(Math.Max(sqrDistance, 0)); }
public DistPoint3Triangle3(Vector3d PointIn, Triangle3d TriangleIn) { point = PointIn; triangle = TriangleIn; }
public DistLine3Triangle3(Line3d LineIn, Triangle3d TriangleIn) { this.triangle = TriangleIn; this.line = LineIn; }
public DistTriangle3Triangle3(Triangle3d Triangle0in, Triangle3d Triangle1in) { this.triangle0 = Triangle0in; this.triangle1 = Triangle1in; }
private static bool Intersects(ref Triangle3d triangle0, ref Triangle3d triangle1, ref IntersectionType type) { // Get edge vectors for triangle0. Vector3dTuple3 E0; E0.V0 = triangle0.V1 - triangle0.V0; E0.V1 = triangle0.V2 - triangle0.V1; E0.V2 = triangle0.V0 - triangle0.V2; // Get normal vector of triangle0. Vector3d N0 = E0.V0.UnitCross(ref E0.V1); // Project triangle1 onto normal line of triangle0, test for separation. double N0dT0V0 = N0.Dot(ref triangle0.V0); double min1, max1; ProjectOntoAxis(ref triangle1, ref N0, out min1, out max1); if (N0dT0V0 < min1 || N0dT0V0 > max1) { return(false); } // Get edge vectors for triangle1. Vector3dTuple3 E1; E1.V0 = triangle1.V1 - triangle1.V0; E1.V1 = triangle1.V2 - triangle1.V1; E1.V2 = triangle1.V0 - triangle1.V2; // Get normal vector of triangle1. Vector3d N1 = E1.V0.UnitCross(ref E1.V1); Vector3d dir; double min0, max0; int i0, i1; Vector3d N0xN1 = N0.UnitCross(ref N1); if (N0xN1.Dot(ref N0xN1) >= MathUtil.ZeroTolerance) { // Triangles are not parallel. // Project triangle0 onto normal line of triangle1, test for // separation. double N1dT1V0 = N1.Dot(ref triangle1.V0); ProjectOntoAxis(ref triangle0, ref N1, out min0, out max0); if (N1dT1V0 < min0 || N1dT1V0 > max0) { return(false); } // Directions E0[i0]xE1[i1]. for (i1 = 0; i1 < 3; ++i1) { for (i0 = 0; i0 < 3; ++i0) { dir = E0[i0].UnitCross(E1[i1]); // could pass ref if we reversed these...need to negate? ProjectOntoAxis(ref triangle0, ref dir, out min0, out max0); ProjectOntoAxis(ref triangle1, ref dir, out min1, out max1); if (max0 < min1 || max1 < min0) { return(false); } } } // The test query does not know the intersection set. type = IntersectionType.Unknown; } else // Triangles are parallel (and, in fact, coplanar). // Directions N0xE0[i0]. { for (i0 = 0; i0 < 3; ++i0) { dir = N0.UnitCross(E0[i0]); ProjectOntoAxis(ref triangle0, ref dir, out min0, out max0); ProjectOntoAxis(ref triangle1, ref dir, out min1, out max1); if (max0 < min1 || max1 < min0) { return(false); } } // Directions N1xE1[i1]. for (i1 = 0; i1 < 3; ++i1) { dir = N1.UnitCross(E1[i1]); ProjectOntoAxis(ref triangle0, ref dir, out min0, out max0); ProjectOntoAxis(ref triangle1, ref dir, out min1, out max1); if (max0 < min1 || max1 < min0) { return(false); } } // The test query does not know the intersection set. type = IntersectionType.Plane; } return(true); }
bool IntersectsSegment(ref Plane3d plane, ref Triangle3d triangle, Vector3d end0, Vector3d end1) { // Compute the 2D representations of the triangle vertices and the // segment endpoints relative to the plane of the triangle. Then // compute the intersection in the 2D space. // Project the triangle and segment onto the coordinate plane most // aligned with the plane normal. int maxNormal = 0; double fmax = Math.Abs(plane.Normal.x); double absMax = Math.Abs(plane.Normal.y); if (absMax > fmax) { maxNormal = 1; fmax = absMax; } absMax = Math.Abs(plane.Normal.z); if (absMax > fmax) { maxNormal = 2; } Triangle2d projTri = new Triangle2d(); Vector2d projEnd0 = Vector2d.Zero, projEnd1 = Vector2d.Zero; int i; if (maxNormal == 0) { // Project onto yz-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].yz; projEnd0.x = end0.y; projEnd0.y = end0.z; projEnd1.x = end1.y; projEnd1.y = end1.z; } } else if (maxNormal == 1) { // Project onto xz-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].xz; projEnd0.x = end0.x; projEnd0.y = end0.z; projEnd1.x = end1.x; projEnd1.y = end1.z; } } else { // Project onto xy-plane. for (i = 0; i < 3; ++i) { projTri[i] = triangle[i].xy; projEnd0.x = end0.x; projEnd0.y = end0.y; projEnd1.x = end1.x; projEnd1.y = end1.y; } } Segment2d projSeg = new Segment2d(projEnd0, projEnd1); IntrSegment2Triangle2 calc = new IntrSegment2Triangle2(projSeg, projTri); if (!calc.Find()) { return(false); } Vector2dTuple2 intr = new Vector2dTuple2(); if (calc.Type == IntersectionType.Segment) { Result = IntersectionResult.Intersects; Type = IntersectionType.Segment; Quantity = 2; intr.V0 = calc.Point0; intr.V1 = calc.Point1; } else { Debug.Assert(calc.Type == IntersectionType.Point); //"Intersection must be a point\n"; Result = IntersectionResult.Intersects; Type = IntersectionType.Point; Quantity = 1; intr.V0 = calc.Point0; } // Unproject the segment of intersection. if (maxNormal == 0) { double invNX = ((double)1) / plane.Normal.x; for (i = 0; i < Quantity; ++i) { double y = intr[i].x; double z = intr[i].y; double x = invNX * (plane.Constant - plane.Normal.y * y - plane.Normal.z * z); Points[i] = new Vector3d(x, y, z); } } else if (maxNormal == 1) { double invNY = ((double)1) / plane.Normal.y; for (i = 0; i < Quantity; ++i) { double x = intr[i].x; double z = intr[i].y; double y = invNY * (plane.Constant - plane.Normal.x * x - plane.Normal.z * z); Points[i] = new Vector3d(x, y, z); } } else { double invNZ = ((double)1) / plane.Normal.z; for (i = 0; i < Quantity; ++i) { double x = intr[i].x; double y = intr[i].y; double z = invNZ * (plane.Constant - plane.Normal.x * x - plane.Normal.y * y); Points[i] = new Vector3d(x, y, z); } } return(true); }
private void Remove(TriangleRemoval rem = TriangleRemoval.contained) { #if ACAD var lastColor = 0; #endif DMeshAABBTree3 spatial = new DMeshAABBTree3(CutMesh, true); spatial.WindingNumber(Vector3d.Zero); SafeListBuilder <int> containedT = new SafeListBuilder <int>(); SafeListBuilder <int> removeAnywayT = new SafeListBuilder <int>(); // if the windinging number for the centroid point candidate triangles // is one or more (or close for safety), then it's inside the volume of cutMesh // gParallel.ForEach(Target.TriangleIndices(), (tid) => { if (Target.GetTriArea(tid) < VertexSnapTol) { removeAnywayT.SafeAdd(tid); return; // parallel: equivalent to continue. } Vector3d v = Target.GetTriCentroid(tid); if (AttemptPlanarRemoval) { // slightly offset the point to be evaluated. // var nrm = Target.GetTriNormal(tid); v -= nrm * 5 * VertexSnapTol; } var winding = spatial.WindingNumber(v); bool IsInternal = winding > 0.9; #if ACAD // temporarily here for debug purposes var wantColor = IsInternal ? 1 : 2; if (lastColor != wantColor) { Debug.WriteLine($"-LAYER set L{wantColor}"); Debug.WriteLine($""); lastColor = wantColor; } Triangle3d tri = new Triangle3d(); Target.GetTriVertices(tid, ref tri.V0, ref tri.V1, ref tri.V2); Debug.WriteLine($"3DPOLY {tri.V0.CommaDelimited} {tri.V1.CommaDelimited} {tri.V2.CommaDelimited} {tri.V0.CommaDelimited} {v.CommaDelimited} "); #endif if (IsInternal) { containedT.SafeAdd(tid); } }); if (rem == TriangleRemoval.contained) { MeshEditor.RemoveTriangles(Target, containedT.Result); } else if (rem == TriangleRemoval.external) { var ext = Target.TriangleIndices().Except(containedT.Result); MeshEditor.RemoveTriangles(Target, ext); } MeshEditor.RemoveTriangles(Target, removeAnywayT.Result); // [RMS] construct set of on-cut vertices? This is not // necessarily all boundary vertices... CutVertices = new List <int>(); foreach (int vid in SegmentInsertVertices) { if (Target.IsVertex(vid)) { CutVertices.Add(vid); } } }