// calculating normal using Newell's method private void CalcNormal(List <Vector3m> points) { Vector3m normal = Vector3m.Zero(); for (var i = 0; i < points.Count; i++) { var j = (i + 1) % (points.Count); normal.X += (points[i].Y - points[j].Y) * (points[i].Z + points[j].Z); normal.Y += (points[i].Z - points[j].Z) * (points[i].X + points[j].X); normal.Z += (points[i].X - points[j].X) * (points[i].Y + points[j].Y); } Normal = normal; }
public bool RaySegmentIntersection(out Vector3m intersection, out Rational distanceSquared, Vector3m linePoint1, Vector3m lineVec1, Vector3m linePoint3, Vector3m linePoint4, Vector3m direction) { var lineVec2 = linePoint4 - linePoint3; Vector3m lineVec3 = linePoint3 - linePoint1; Vector3m crossVec1and2 = lineVec1.Cross(lineVec2); Vector3m crossVec3and2 = lineVec3.Cross(lineVec2); var res = Misc.PointLineDistance(linePoint3, linePoint4, linePoint1); if (res == 0) // line and ray are collinear { var p = linePoint1 + lineVec1; var res2 = Misc.PointLineDistance(linePoint3, linePoint4, p); if (res2 == 0) { var s = linePoint3 - linePoint1; if (s.X == direction.X && s.Y == direction.Y && s.Z == direction.Z) { intersection = linePoint3; distanceSquared = s.LengthSquared(); return(true); } } } //is coplanar, and not parallel if (/*planarFactor == 0.0f && */ crossVec1and2.LengthSquared() > 0) { var s = crossVec3and2.Dot(crossVec1and2) / crossVec1and2.LengthSquared(); if (s >= 0) { intersection = linePoint1 + (lineVec1 * s); distanceSquared = (lineVec1 * s).LengthSquared(); if ((intersection - linePoint3).LengthSquared() + (intersection - linePoint4).LengthSquared() <= lineVec2.LengthSquared()) { return(true); } } } intersection = Vector3m.Zero(); distanceSquared = 0; return(false); }
public void Triangulate() { if (Normal.Equals(Vector3m.Zero())) { throw new Exception("The input is not a valid polygon"); } if (_holes != null && _holes.Count > 0) { ProcessHoles(); } List <ConnectionEdge> nonConvexPoints = FindNonConvexPoints(_mainPointList); if (nonConvexPoints.Count == _mainPointList.PointCount) { throw new ArgumentException("The triangle input is not valid"); } while (_mainPointList.PointCount > 2) { bool guard = false; foreach (var cur in _mainPointList.GetPolygonCirculator()) { if (!IsConvex(cur)) { continue; } if (!IsPointInTriangle(cur.Prev.Origin, cur.Origin, cur.Next.Origin, nonConvexPoints)) { // cut off ear guard = true; Result.Add(cur.Prev.Origin); Result.Add(cur.Origin); Result.Add(cur.Next.Origin); // Check if prev and next are still nonconvex. If not, then remove from non convex list if (IsConvex(cur.Prev)) { int index = nonConvexPoints.FindIndex(x => x == cur.Prev); if (index >= 0) { nonConvexPoints.RemoveAt(index); } } if (IsConvex(cur.Next)) { int index = nonConvexPoints.FindIndex(x => x == cur.Next); if (index >= 0) { nonConvexPoints.RemoveAt(index); } } _mainPointList.Remove(cur); break; } } if (PointsOnLine(_mainPointList)) { break; } if (!guard) { throw new Exception("No progression. The input must be wrong"); } } }