public static int WhichSide(Triangle2d V, Vector2D P, Vector2D D) { // Vertices are projected to the form P+t*D. Return value is +1 if all // t > 0, -1 if all t < 0, 0 otherwise, in which case the line splits the // triangle. int positive = 0, negative = 0, zero = 0; for (int i = 0; i < 3; ++i) { double t = D.Dot(V[i] - P); if (t > (double)0) { ++positive; } else if (t < (double)0) { ++negative; } else { ++zero; } if (positive > 0 && negative > 0) { return(0); } } return(zero == 0 ? (positive > 0 ? 1 : -1) : 0); }
public static void TriangleLineRelations( Vector2D origin, Vector2D direction, Triangle2d tri, ref Vector3D dist, ref Vector3i sign, ref int positive, ref int negative, ref int zero) { positive = 0; negative = 0; zero = 0; for (int i = 0; i < 3; ++i) { Vector2D diff = tri[i] - origin; dist[i] = diff.DotPerp(direction); if (dist[i] > math.MathUtil.ZeroTolerance) { sign[i] = 1; ++positive; } else if (dist[i] < -math.MathUtil.ZeroTolerance) { sign[i] = -1; ++negative; } else { dist[i] = 0.0; sign[i] = 0; ++zero; } } }
/// <summary> /// Gets triangle. /// </summary> /// <param name="index">The triangle index.</param> /// <param name="positionComponent">The component where we look for position, must be /// correct format.</param> /// <remarks>This is not performance wise getter.</remarks> public Triangle2d Get2d(string positionComponent, uint index) { Triangle2d t = new Triangle2d(); Get(positionComponent, index, t); return(t); }
//#foreach instanced to 'Double2' /// <summary> /// Gets triangle. /// </summary> /// <param name="index">The triangle triangle index.</param> /// <remarks>This is not performance wise getter.</remarks> /// <returns></returns> public Triangle2d Get2d(uint index) { Triangle2d t = new Triangle2d(); Get(CommonComponents.Position, index, t); return(t); }
/// <summary> /// An array getter, optimized by reusing mappings. /// </summary> /// <param name="triangleIndex">The triangle index offset.</param> /// <param name="positionComponent">The position component.</param> /// <param name="storage">Where to store result.</param> public void Get(string positionComponent, uint triangleIndex, Triangle2d[] storage) { if (triangleIndex + storage.Length >= shapeCount) { throw new ArgumentException("Index out of range, not that many triangles."); } if (indexBuffer != null) { uint[] indices = indexBuffer.Getui(triangleIndex * 3, (uint)storage.Length * 3); Vector2d[] data = query.Get2d(positionComponent, indices); for (int i = 0; i < storage.Length; i++) { storage[i] = new Triangle2d(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]); } } else { Vector2d[] data = query.Get2d(positionComponent, triangleIndex * 3, (uint)storage.Length * 3); for (int i = 0; i < storage.Length; i++) { storage[i] = new Triangle2d(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]); } } }
public KAABBTree(IList <Triangle2d> mesh) { _boxes = new AxisAlignedBox2d[NumberOfAlignment]; for (var i = 0; i < NumberOfAlignment; ++i) { var i1 = i; _boxes[i] = mesh.Select(tra => tra.Rotate(Alignment[i1])).GetBBox(); } var alignmentToSplitBy = Random.Next(NumberOfAlignment); mesh = (_boxes[alignmentToSplitBy].Height > _boxes[alignmentToSplitBy].Width ? mesh.OrderBy(tra => (Alignment[alignmentToSplitBy] * tra.V0).y) : mesh.OrderBy(tra => (Alignment[alignmentToSplitBy] * tra.V0).x)).ToList(); if (mesh.Count != 1) { _isALeef = false; var midIndex = mesh.Count / 2; _left = new KAABBTree(mesh.Take(midIndex).ToList()); _right = new KAABBTree(mesh.Skip(midIndex).Take(mesh.Count - midIndex).ToList()); } else { _isALeef = true; _mesh = mesh.First(); } }
public void Contains_Triangle2d_V2d() { var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)); Assert.IsTrue(t.Contains(new V2d(1, 1))); Assert.IsTrue(t.Contains(new V2d(2, 0))); Assert.IsTrue(!t.Contains(new V2d(0, 0.000001))); }
public void Contains_Triangle2d_Triangle2d() { var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)); Assert.IsTrue(t.Contains(new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)))); Assert.IsTrue(t.Contains(new Triangle2d(new V2d(0.2, 0.1), new V2d(1.5, 0.5), new V2d(1, 1.5)))); Assert.IsTrue(!t.Contains(new Triangle2d(new V2d(0.2, 0.1), new V2d(1.5, 0.5), new V2d(1, 2.000001)))); Assert.IsTrue(!t.Contains(new Triangle2d(new V2d(-1, -1), new V2d(3, -1), new V2d(1, 5)))); }
public void Contains_Triangle2d_Quad2d() { var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)); Assert.IsTrue(t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2), new V2d(1, 2)))); Assert.IsTrue(t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1.5, 0.2), new V2d(0.5, 0.2)))); Assert.IsTrue(!t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1.5, 0.2), new V2d(0.5, 1.1)))); Assert.IsTrue(!t.Contains(new Quad2d(new V2d(-1, -1), new V2d(5, -1), new V2d(5, 5), new V2d(0, 5)))); }
public void Contains_Triangle2d_Circle2d() { var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)); Assert.IsTrue(t.Contains(new Circle2d(new V2d(1, 1), 0.5))); Assert.IsTrue(t.Contains(new Circle2d(new V2d(1, 2), 0.0))); Assert.IsTrue(!t.Contains(new Circle2d(new V2d(1, 0.1), 0.100001))); Assert.IsTrue(!t.Contains(new Circle2d(new V2d(1, 2), 10))); }
public void Contains_Triangle2d_Line2d() { var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2)); Assert.IsTrue(t.Contains(new Line2d(new V2d(0, 0), new V2d(2, 0)))); Assert.IsTrue(t.Contains(new Line2d(new V2d(2, 0), new V2d(1, 2)))); Assert.IsTrue(t.Contains(new Line2d(new V2d(1, 2), new V2d(0, 0)))); Assert.IsTrue(t.Contains(new Line2d(new V2d(0.5, 0.1), new V2d(1.5, 0.2)))); Assert.IsTrue(!t.Contains(new Line2d(new V2d(0.5, 0.1), new V2d(2, 2)))); Assert.IsTrue(!t.Contains(new Line2d(new V2d(0.1, 0.2), new V2d(1.1, 10)))); }
/// <summary> /// Fills a triangle at index. /// </summary> /// <param name="index">The index.</param> /// <param name="triangle">The triangle to be filled.</param> public void Get(uint index, [NotNull] Triangle2d triangle) { int idx = (int)index; if (IsIndexed) { triangle.A = vertices[(int)indices[idx * 3]]; triangle.B = vertices[(int)indices[idx * 3 + 1]]; triangle.C = vertices[(int)indices[idx * 3 + 2]]; } else { triangle.A = vertices[3 * idx]; triangle.B = vertices[3 * idx + 1]; triangle.C = vertices[3 * idx + 2]; } }
public AABBTree(IList <Triangle2d> mesh) { _box = mesh.GetBBox(); mesh = (_box.Height > _box.Width ? mesh.OrderBy(tra => tra.V0.y) : mesh.OrderBy(tra => tra.V0.x)).ToList(); if (mesh.Count != 1) { _isALeef = false; var midIndex = mesh.Count / 2; _left = new AABBTree(mesh.Take(midIndex).ToList()); _right = new AABBTree(mesh.Skip(midIndex).Take(mesh.Count - midIndex).ToList()); } else { _isALeef = true; _mesh = mesh.First(); } }
/// <summary> /// Gets triangle. /// </summary> /// <param name="index">The triangle triangle index.</param> /// <remarks>This accessor is not to be used in performance critical parts of applications.</remarks> /// <returns></returns> public void Get(string positionComponent, uint index, Triangle2d storage) { if (index >= shapeCount) { throw new ArgumentException("Index out of range, not that many triangles."); } if (indexBuffer != null) { uint[] indices = indexBuffer.Getui(index * 3, 3); storage.A = query.Get2d(positionComponent, indices[0]); storage.B = query.Get2d(positionComponent, indices[1]); storage.C = query.Get2d(positionComponent, indices[2]); } else { storage.A = query.Get2d(positionComponent, index * 3); storage.B = query.Get2d(positionComponent, index * 3 + 1); storage.C = query.Get2d(positionComponent, index * 3 + 2); } }
/// <summary> /// Gets triangle. /// </summary> /// <param name="index">The triangle index.</param> /// <param name="positionComponent">The component where we look for position, must be /// Vector2f format.</param> /// <remarks>This is not performance wise getter.</remarks> public void Get(uint index, Triangle2d storage) { Get(CommonComponents.Position, index, storage); }
public void CodeTriangle2d(ref Triangle2d v) { AddValue(v.ToString()); }
public IntrSegment2Triangle2(Segment2d s, Triangle2d t) { segment = s; triangle = t; }
public void CodeTriangle2d(ref Triangle2d v) { CodeV2d(ref v.P0); CodeV2d(ref v.P1); CodeV2d(ref v.P2); }
public IntrTriangle2Triangle2(Triangle2d t0, Triangle2d t1) { triangle0 = t0; triangle1 = t1; Points = null; }
/// <summary> /// Generates a uniform distributed random sample on the given triangle using /// two random variables x1 and x2. /// </summary> public static V2d Triangle(Triangle2d t, double x1, double x2) { return(Triangle(t.P0, t.P1, t.P2, x1, x2)); }
public IntrLine2Triangle2(Line2d l, Triangle2d t) { line = l; triangle = t; }
public static void GetInterval(Vector2D origin, Vector2D direction, Triangle2d tri, Vector3D dist, Vector3i sign, ref Vector2D param) { // Project triangle onto line. Vector3D proj = Vector3D.Zero; int i; for (i = 0; i < 3; ++i) { Vector2D diff = tri[i] - origin; proj[i] = direction.Dot(diff); } // Compute transverse intersections of triangle edges with line. double numer, denom; int i0, i1, i2; int quantity = 0; for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++) { if (sign[i0] * sign[i1] < 0) { if (quantity >= 2) { throw new Exception("IntrLine2Triangle2.GetInterval: too many intersections!"); } numer = dist[i0] * proj[i1] - dist[i1] * proj[i0]; denom = dist[i0] - dist[i1]; param[quantity++] = numer / denom; } } // Check for grazing contact. if (quantity < 2) { for (i0 = 1, i1 = 2, i2 = 0; i2 < 3; i0 = i1, i1 = i2++) { if (sign[i2] == 0) { if (quantity >= 2) { throw new Exception("IntrLine2Triangle2.GetInterval: too many intersections!"); } param[quantity++] = proj[i2]; } } } // Sort. if (quantity < 1) { throw new Exception("IntrLine2Triangle2.GetInterval: need at least one intersection"); } if (quantity == 2) { if (param[0] > param[1]) { double save = param[0]; param[0] = param[1]; param[1] = save; } } else { param[1] = param[0]; } }
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); }
/// <summary> /// Gets the centroid of the polyline. /// </summary> /// <param name="pl">The instance to which the method applies.</param> /// <returns>The centroid of the polyline (OCS coordinates).</returns> public static Point2d Centroid2d(this Polyline pl) { Point2d cen = new Point2d(); Triangle2d tri = new Triangle2d(); CircularArc2d arc = new CircularArc2d(); double tmpArea; double area = 0.0; int last = pl.NumberOfVertices - 1; Point2d p0 = pl.GetPoint2dAt(0); double bulge = pl.GetBulgeAt(0); if (bulge != 0.0) { arc = pl.GetArcSegment2dAt(0); area = arc.AlgebricArea(); cen = arc.Centroid() * area; } for (int i = 1; i < last; i++) { tri.Set(p0, pl.GetPoint2dAt(i), pl.GetPoint2dAt(i + 1)); tmpArea = tri.AlgebricArea; cen += (tri.Centroid * tmpArea).GetAsVector(); area += tmpArea; bulge = pl.GetBulgeAt(i); if (bulge != 0.0) { arc = pl.GetArcSegment2dAt(i); tmpArea = arc.AlgebricArea(); area += tmpArea; cen += (arc.Centroid() * tmpArea).GetAsVector(); } } bulge = pl.GetBulgeAt(last); if ((bulge != 0.0) && (pl.Closed == true)) { arc = pl.GetArcSegment2dAt(last); tmpArea = arc.AlgebricArea(); area += tmpArea; cen += (arc.Centroid() * tmpArea).GetAsVector(); } return cen.DivideBy(area); }
/// <summary> /// Obtains a collection of triangles. /// </summary> /// <param name="index">The base index.</param> /// <param name="count">Number of triangles.</param> /// <returns>The triangle collection.</returns> public Triangle2d[] Get(uint index, uint count) { Triangle2d[] data = new Triangle2d[count]; Get(index, data); return(data); }
public static Triangle2d Rotate(this Triangle2d tra, Matrix2d rotationMatrix) { return(new Triangle2d(rotationMatrix * tra[0], rotationMatrix * tra[1], rotationMatrix * tra[2])); }
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); }
/// <summary> /// An array getter, optimized by reusing mappings. /// </summary> /// <param name="triangleIndex">The triangle index offset.</param> /// <param name="positionComponent">The position component.</param> /// <param name="count">Number of triangles.</param> public Triangle2d[] Get2d(string positionComponent, uint triangleIndex, uint count) { Triangle2d[] data = new Triangle2d[count]; Get(positionComponent, triangleIndex, data); return(data); }
public void CodeTriangle2d(ref Triangle2d v) { throw new NotImplementedException(); }
/// <summary> /// Generates a uniform distributed random sample on the given triangle using /// two random series (seriesIndex, seriesIndex + 1). /// </summary> public static V2d Triangle(Triangle2d t, IRandomSeries rnd, int seriesIndex) { return(Triangle(t.P0, t.P1, t.P2, rnd.UniformDouble(seriesIndex), rnd.UniformDouble(seriesIndex + 1))); }