Triangle GetAdjacent(DelaunayPoint start, DelaunayPoint end) { double t = 0; double s = SegmentsIntersect(m_v[0], m_v[1], start, end, t); if (t >= 0 && t <= 1 && s >= 0 && s <= 1) { return(adjacentFace[0]); } s = SegmentsIntersect(m_v[1], m_v[2], start, end, t); if (t >= 0 && t <= 1 && s >= 0 && s <= 1) { return(adjacentFace[1]); } s = SegmentsIntersect(m_v[2], m_v[0], start, end, t); if (t >= 0 && t <= 1 && s >= 0 && s <= 1) { return(adjacentFace[2]); } return(null); }
float SegmentsIntersect(DelaunayPoint a, DelaunayPoint b, DelaunayPoint c, DelaunayPoint d, double t) { //what if denominator is zero?? double diff0 = (c.Y - a.Y) * MULTIPLIER; double diff1 = (d.X - c.X) * MULTIPLIER; double diff2 = (a.X - c.X) * MULTIPLIER; double diff3 = (d.Y - c.Y) * MULTIPLIER; double diff4 = (b.Y - a.Y) * MULTIPLIER; double diff5 = (b.X - a.X) * MULTIPLIER; t = (diff0 * diff1 + diff2 * diff3) / (diff4 * diff1 - diff5 * diff3); double s = (-diff2 * diff4 - diff0 * diff5) / (diff3 * diff5 - diff1 * diff4); if (Math.Abs(t) <= VERY_SMALL_DIST) { t = 0; } if (Math.Abs(s) <= VERY_SMALL_DIST) { s = 0; } return((float)s); }
bool IsClose(DelaunayPoint p, double maxDistance) { if (m_norm == 0) { ComputePlaneParams(); } double dist = Math.Abs((m_a * p.X + m_b * p.Y + m_c * p.Z + m_d) / m_norm); return(dist <= maxDistance); }
private void ForceClockwise() { if (DelaunayGeometry.CrossProduct(m_v[0], m_v[1], m_v[2]) >= 0) { // a positive value indicates counter clockwise // Swapping the first 2 points should be enough DelaunayPoint tmp = m_v[0]; m_v[0] = m_v[1]; m_v[1] = tmp; } }
bool LocateInternalUsingTriangleList(IEnumerable <Triangle> triangles, DelaunayPoint p) { foreach (Triangle triangle in triangles) { if (LocateInternal(triangle, p) != null) { return(true); } } return(false); }
bool LocateInternal(DelaunayPoint p) { if (m_currentTriangle != null) { Triangle newTriangle = LocateInternal(m_currentTriangle, p); if (newTriangle != null) { return(true); } } return(false); }
public Triangle(DelaunayPoint v1, DelaunayPoint v2, DelaunayPoint v3) { m_v = new DelaunayPoint[] { v1, v2, v3 }; ForceClockwise(); adjacentFace = new Triangle[3]; centroidX = (float)(v1.X + v2.X + v3.X) / 3.0f; centroidY = (float)(v1.Y + v2.Y + v3.Y) / 3.0f; m_extent = new Extent2D(m_v[0], m_v[1], m_v[2]); }
public bool Contains(DelaunayPoint p) { // Only bother to check if the point is within the initial extents of the Triangle_t if (m_extent.Contains(p.X, p.Y, true)) { return ( (DelaunayGeometry.CrossProduct(m_v[0], p, m_v[1]) >= 0.0) && (DelaunayGeometry.CrossProduct(m_v[1], p, m_v[2]) >= 0.0) && (DelaunayGeometry.CrossProduct(m_v[2], p, m_v[0]) >= 0.0)); } return false; }
public Triangle(DelaunayPoint v1, DelaunayPoint v2, DelaunayPoint v3) { m_v = new DelaunayPoint[] { v1, v2, v3 }; ForceClockwise(); adjacentFace = new Triangle[3]; centroidX = (float)(v1.X + v2.X + v3.X) / 3.0f; centroidY = (float)(v1.Y + v2.Y + v3.Y) / 3.0f; m_extent = new Extent2D(m_v[0], m_v[1], m_v[2]); }
public bool Contains(DelaunayPoint p) { // Only bother to check if the point is within the initial extents of the Triangle_t if (m_extent.Contains(p.X, p.Y, true)) { return( (DelaunayGeometry.CrossProduct(m_v[0], p, m_v[1]) >= 0.0) && (DelaunayGeometry.CrossProduct(m_v[1], p, m_v[2]) >= 0.0) && (DelaunayGeometry.CrossProduct(m_v[2], p, m_v[0]) >= 0.0)); } return(false); }
public bool IsCoincidentWithVertex(DelaunayPoint p) { double distA = (m_v[0].X - p.X) * (m_v[0].X - p.X) + (m_v[0].Y - p.Y) * (m_v[0].Y - p.Y); double distB = (m_v[1].X - p.X) * (m_v[1].X - p.X) + (m_v[1].Y - p.Y) * (m_v[1].Y - p.Y); double distC = (m_v[2].X - p.X) * (m_v[2].X - p.X) + (m_v[2].Y - p.Y) * (m_v[2].Y - p.Y); if ((distA <= VERY_SMALL_DIST) || (distB <= VERY_SMALL_DIST) || (distC <= VERY_SMALL_DIST)) { return(true); } return(false); }
bool LocateInternalBruteForce(DelaunayPoint p) { m_currentTriangle = null; foreach (Triangle triangle in m_newTriangles) { if (triangle.Contains(p)) { m_currentTriangle = triangle; return(true); } } return(false); }
////use this only for direction and nothing else public static float CrossProduct(DelaunayPoint p, DelaunayPoint a, DelaunayPoint b) { // FUTURE: Migrate this into a more appropriate place. //use the multiplier for making sure we handle small numbers correctly double diffax = (double)a.X - p.X; double diffay = (double)a.Y - p.Y; double diffbx = (double)b.X - p.X; double diffby = (double)b.Y - p.Y; double cross = (diffax * diffby - diffbx * diffay); if (cross >= 1.0e-12 || cross <= -1.0e-12) return (float)cross; return 0.0f; }
public bool UpdateTriangle(DelaunayPoint p) { if (m_currentTriangle == null) { return(false); } if (m_currentTriangle.IsCoincidentWithVertex(p)) { return(false); } Update(p); return(true); }
public static Extent2D Circumcircle(DelaunayPoint v1, DelaunayPoint v2, DelaunayPoint v3, double cx, double cy) { const double ERROR_BOUND = 0.005; //http://mathworld.wolfram.com/Circumcircle.html double x1 = v1.X; double x2 = v2.X; double x3 = v3.X; double y1 = v1.Y; double y2 = v2.Y; double y3 = v3.Y; double x1Sq = x1 * x1; double x2Sq = x2 * x2; double x3Sq = x3 * x3; double y1Sq = y1 * y1; double y2Sq = y2 * y2; double y3Sq = y3 * y3; double a = (x1 - x2) * (y2 - y3) - (y1 - y2) * (x2 - x3); double bx = -((x1Sq + y1Sq - x2Sq - y2Sq) * (y2 - y3) - (x2Sq + y2Sq - x3Sq - y3Sq) * (y1 - y2)); double by = ((x1Sq + y1Sq - x2Sq - y2Sq) * (x2 - x3) - (x2Sq + y2Sq - x3Sq - y3Sq) * (x1 - x2)); double c = -((x1Sq + y1Sq) * (x2 * y3 - x3 * y2) - (x2Sq + y2Sq) * (x1 * y3 - x3 * y1) + (x3Sq + y3Sq) * (x1 * y2 - x2 * y1)); Extent2D extent = null; if (a == 0.0f) { extent = new Extent2D(cx - ERROR_BOUND, cx + ERROR_BOUND, cy - ERROR_BOUND, cy + ERROR_BOUND); } else { double x0 = -bx / (2.0f * a); double y0 = -by / (2.0f * a); double numerator = bx * bx + by * by - 4.0f * a * c; double rad = 0; if (numerator >= 0) { rad = Math.Sqrt(numerator) / (2.0f * Math.Abs(a)); } extent = new Extent2D(x0 - rad - ERROR_BOUND, x0 + rad + ERROR_BOUND, y0 - rad - ERROR_BOUND, y0 + rad + ERROR_BOUND); } return(extent); }
// Returns true if the point is contained in the triangle otherwise returns false // if false then ref is the next triangle public bool Contains(DelaunayPoint p, ref Triangle next) { //unrolled the dot product logic for optimization // a refers to point m_v[0] // b refers to point m_v[1] // c refers to point m_v[1] // p is the point double diffax = (m_v[0].X - p.X); double diffay = (m_v[0].Y - p.Y); double diffcx = (m_v[2].X - p.X); double diffcy = (m_v[2].Y - p.Y); double aXc = (diffax * diffcy - diffcx * diffay); if (aXc < 0.0) // if negative point is outside of edge a,c { next = adjacentFace[2]; return(false); } else { double diffbx = (m_v[1].X - p.X); double diffby = (m_v[1].Y - p.Y); double cXb = (diffcx * diffby - diffbx * diffcy); if (cXb < 0.0) // if { next = adjacentFace[1]; return(false); } else { double bXa = (diffbx * diffay - diffax * diffby); if (bXa < 0.0) { next = adjacentFace[0]; return(false); } } } return(true); }
////use this only for direction and nothing else public static float CrossProduct(DelaunayPoint p, DelaunayPoint a, DelaunayPoint b) { // FUTURE: Migrate this into a more appropriate place. //use the multiplier for making sure we handle small numbers correctly double diffax = (double)a.X - p.X; double diffay = (double)a.Y - p.Y; double diffbx = (double)b.X - p.X; double diffby = (double)b.Y - p.Y; double cross = (diffax * diffby - diffbx * diffay); if (cross >= 1.0e-12 || cross <= -1.0e-12) { return((float)cross); } return(0.0f); }
public static Extent2D Circumcircle(DelaunayPoint v1, DelaunayPoint v2, DelaunayPoint v3, double cx, double cy) { const double ERROR_BOUND = 0.005; //http://mathworld.wolfram.com/Circumcircle.html double x1 = v1.X; double x2 = v2.X; double x3 = v3.X; double y1 = v1.Y; double y2 = v2.Y; double y3 = v3.Y; double x1Sq = x1 * x1; double x2Sq = x2 * x2; double x3Sq = x3 * x3; double y1Sq = y1 * y1; double y2Sq = y2 * y2; double y3Sq = y3 * y3; double a = (x1 - x2) * (y2 - y3) - (y1 - y2) * (x2 - x3); double bx = -((x1Sq + y1Sq - x2Sq - y2Sq) * (y2 - y3) - (x2Sq + y2Sq - x3Sq - y3Sq) * (y1 - y2)); double by = ((x1Sq + y1Sq - x2Sq - y2Sq) * (x2 - x3) - (x2Sq + y2Sq - x3Sq - y3Sq) * (x1 - x2)); double c = -((x1Sq + y1Sq) * (x2 * y3 - x3 * y2) - (x2Sq + y2Sq) * (x1 * y3 - x3 * y1) + (x3Sq + y3Sq) * (x1 * y2 - x2 * y1)); Extent2D extent = null; if (a == 0.0f) { extent = new Extent2D(cx - ERROR_BOUND, cx + ERROR_BOUND, cy - ERROR_BOUND, cy + ERROR_BOUND); } else { double x0 = -bx / (2.0f * a); double y0 = -by / (2.0f * a); double numerator = bx * bx + by * by - 4.0f * a * c; double rad = 0; if (numerator >= 0) rad = Math.Sqrt(numerator) / (2.0f * Math.Abs(a)); extent = new Extent2D(x0 - rad - ERROR_BOUND, x0 + rad + ERROR_BOUND, y0 - rad - ERROR_BOUND, y0 + rad + ERROR_BOUND); } return extent; }
public bool CircumCircleContains(DelaunayPoint p) { // http://www.cs.cmu.edu/~quake/robust.html double a1 = (double)m_v[0].X - p.X; double a2 = (double)m_v[0].Y - p.Y; double a3 = a1*a1 + a2*a2; double b1 = (double)m_v[1].X - p.X; double b2 = (double)m_v[1].Y - p.Y; double b3 = b1*b1 + b2*b2; double c1 = (double)m_v[2].X - p.X; double c2 = (double)m_v[2].Y - p.Y; double c3 = c1*c1 + c2*c2; double det = a1 * (b2 * c3 - b3 * c2) - a2 * (b1 * c3 - b3 * c1) + a3 * (b1 * c2 - b2 * c1); return !(det >= double.Epsilon); }
public bool Locate(DelaunayPoint p) { // Attempt to walk to the triangle. if (LocateInternal(p)) { return(true); } else { //// Attempt to walk to the triangle using the cell's boundary triangles. //if(LocateInternalUsingTriangleList(cell->BoundaryTriangles(), p)) //{ // return true; //} // Last ditch effort to find the triangle looking through memory -- O(n) return(LocateInternalBruteForce(p)); } }
public bool Locate(DelaunayPoint p) { // Attempt to walk to the triangle. if(LocateInternal(p)) { return true; } else { //// Attempt to walk to the triangle using the cell's boundary triangles. //if(LocateInternalUsingTriangleList(cell->BoundaryTriangles(), p)) //{ // return true; //} // Last ditch effort to find the triangle looking through memory -- O(n) return LocateInternalBruteForce(p); } }
public bool CircumCircleContains(DelaunayPoint p) { // http://www.cs.cmu.edu/~quake/robust.html double a1 = (double)m_v[0].X - p.X; double a2 = (double)m_v[0].Y - p.Y; double a3 = a1 * a1 + a2 * a2; double b1 = (double)m_v[1].X - p.X; double b2 = (double)m_v[1].Y - p.Y; double b3 = b1 * b1 + b2 * b2; double c1 = (double)m_v[2].X - p.X; double c2 = (double)m_v[2].Y - p.Y; double c3 = c1 * c1 + c2 * c2; double det = a1 * (b2 * c3 - b3 * c2) - a2 * (b1 * c3 - b3 * c1) + a3 * (b1 * c2 - b2 * c1); return(!(det >= double.Epsilon)); }
void FreeTriangle(Triangle t, bool flush) { if (t == null) { //should never come here, maybe the last ones return; } //make sure we arent deleting the m_currentTriangle if (m_currentTriangle == t) { m_currentTriangle = null; } // TODO: Encapsulate this later if triangles reference edges/vertices via shared_ptr. DelaunayPoint v1 = t.m_v[0]; DelaunayPoint v2 = t.m_v[1]; DelaunayPoint v3 = t.m_v[2]; if (flush) { bool isSuperTriangleVertex = false; for (int i = 0; i < 3; i++) { DelaunayPoint v = t.m_v[i]; if (v == m_superA || v == m_superB || v == m_superC) { isSuperTriangleVertex = true; break; } } if (!isSuperTriangleVertex) { m_outputTriangles.Add(v1.Index); m_outputTriangles.Add(v2.Index); m_outputTriangles.Add(v3.Index); } } //m_trianglesMemoryManager.dealloc(*t); }
Triangle LocateInternal(Triangle startTriangle, DelaunayPoint end) { int step = 0; //first check if the point is in the current Triangle_t while ((startTriangle != null) && !startTriangle.Contains(end, ref startTriangle) && (++step) <= NUM_STEPS_TO_LOCATE) { } if (step > NUM_STEPS_TO_LOCATE) { startTriangle = null; } if (startTriangle == null) { return(null); } m_currentTriangle = startTriangle; return(m_currentTriangle); }
public void Initialize(Extent3D extent, int numPointsToProcess) { double SQRT3 = Math.Sqrt(3); //create one big Triangle_t aka. supertriangle //Make the bounding box slightly bigger, //actually no need for this if coming from streaming delaunay side m_extent = extent; // compute the supertriangle vertices, clockwise order, check the math m_superA = new DelaunayPoint(extent.MinX - extent.RangeY * SQRT3 / 3.0f, extent.MinY, extent.MinZ, numPointsToProcess); m_superB = new DelaunayPoint(extent.MidpointX, extent.MaxY + extent.RangeX * SQRT3 * 0.5f, extent.MinZ, numPointsToProcess + 1); m_superC = new DelaunayPoint(extent.MaxX + extent.RangeY * SQRT3 / 3.0f, extent.MinY, extent.MinZ, numPointsToProcess + 2); //create the super Triangle_t m_delaunayGraph = new Triangle(m_superA, m_superB, m_superC); //keep track of the current Triangle_t m_currentTriangle = m_delaunayGraph; m_newTriangles = new List<Triangle>(); m_outputTriangles = new List<int>(); }
public void Initialize(Extent3D extent, int numPointsToProcess) { double SQRT3 = Math.Sqrt(3); //create one big Triangle_t aka. supertriangle //Make the bounding box slightly bigger, //actually no need for this if coming from streaming delaunay side m_extent = extent; // compute the supertriangle vertices, clockwise order, check the math m_superA = new DelaunayPoint(extent.MinX - extent.RangeY * SQRT3 / 3.0f, extent.MinY, extent.MinZ, numPointsToProcess); m_superB = new DelaunayPoint(extent.MidpointX, extent.MaxY + extent.RangeX * SQRT3 * 0.5f, extent.MinZ, numPointsToProcess + 1); m_superC = new DelaunayPoint(extent.MaxX + extent.RangeY * SQRT3 / 3.0f, extent.MinY, extent.MinZ, numPointsToProcess + 2); //create the super Triangle_t m_delaunayGraph = new Triangle(m_superA, m_superB, m_superC); //keep track of the current Triangle_t m_currentTriangle = m_delaunayGraph; m_newTriangles = new List <Triangle>(); m_outputTriangles = new List <int>(); }
bool LocateInternalBruteForce(DelaunayPoint p) { m_currentTriangle = null; foreach (Triangle triangle in m_newTriangles) { if (triangle.Contains(p)) { m_currentTriangle = triangle; return true; } } return false; }
Triangle LocateInternal(Triangle startTriangle, DelaunayPoint end) { int step = 0; //first check if the point is in the current Triangle_t while((startTriangle != null) && !startTriangle.Contains(end, ref startTriangle) && (++step) <= NUM_STEPS_TO_LOCATE) { } if(step > NUM_STEPS_TO_LOCATE) startTriangle = null; if(startTriangle == null) return null; m_currentTriangle = startTriangle; return m_currentTriangle; }
bool LocateInternal(DelaunayPoint p) { if(m_currentTriangle != null) { Triangle newTriangle = LocateInternal(m_currentTriangle, p); if(newTriangle != null) return true; } return false; }
public bool UpdateTriangle(DelaunayPoint p) { if (m_currentTriangle == null) return false; if (m_currentTriangle.IsCoincidentWithVertex(p)) return false; Update(p); return true; }
bool IsClose(DelaunayPoint p, double maxDistance) { if (m_norm == 0) ComputePlaneParams(); double dist = Math.Abs((m_a * p.X + m_b * p.Y + m_c * p.Z + m_d) / m_norm); return (dist <= maxDistance); }
// Returns true if the point is contained in the triangle otherwise returns false // if false then ref is the next triangle public bool Contains(DelaunayPoint p, ref Triangle next) { //unrolled the dot product logic for optimization // a refers to point m_v[0] // b refers to point m_v[1] // c refers to point m_v[1] // p is the point double diffax = (m_v[0].X - p.X); double diffay = (m_v[0].Y - p.Y); double diffcx = (m_v[2].X - p.X); double diffcy = (m_v[2].Y - p.Y); double aXc = (diffax * diffcy - diffcx * diffay); if(aXc < 0.0) // if negative point is outside of edge a,c { next = adjacentFace[2]; return false; } else { double diffbx = (m_v[1].X - p.X); double diffby = (m_v[1].Y - p.Y); double cXb = (diffcx * diffby - diffbx * diffcy); if(cXb < 0.0) // if { next = adjacentFace[1]; return false; } else { double bXa = (diffbx * diffay - diffax * diffby); if(bXa < 0.0) { next = adjacentFace[0]; return false; } } } return true; }
bool Overlaps(Extent2D extent) { // Check simplist case - triangle inside extent. if (extent.Contains(m_extent)) { return(true); } // Use right-hand rule for each triangle segment against all points of extent rectangle. DelaunayPoint p1 = new DelaunayPoint(extent.MinX, extent.MinY, 0.0f, 0); DelaunayPoint p2 = new DelaunayPoint(extent.MaxX, extent.MinY, 0.0f, 0); DelaunayPoint p3 = new DelaunayPoint(extent.MaxX, extent.MaxY, 0.0f, 0); DelaunayPoint p4 = new DelaunayPoint(extent.MinX, extent.MaxY, 0.0f, 0); int ar = 0; if (DelaunayGeometry.CrossProduct(m_v[0], p1, m_v[1]) >= 0.0f) { ++ar; } if (DelaunayGeometry.CrossProduct(m_v[0], p2, m_v[1]) >= 0.0f) { ++ar; } if (DelaunayGeometry.CrossProduct(m_v[0], p3, m_v[1]) >= 0.0f) { ++ar; } if (DelaunayGeometry.CrossProduct(m_v[0], p4, m_v[1]) >= 0.0f) { ++ar; } int br = 0; if (DelaunayGeometry.CrossProduct(m_v[1], p1, m_v[2]) >= 0.0f) { ++br; } if (DelaunayGeometry.CrossProduct(m_v[1], p2, m_v[2]) >= 0.0f) { ++br; } if (DelaunayGeometry.CrossProduct(m_v[1], p3, m_v[2]) >= 0.0f) { ++br; } if (DelaunayGeometry.CrossProduct(m_v[1], p4, m_v[2]) >= 0.0f) { ++br; } int cr = 0; if (DelaunayGeometry.CrossProduct(m_v[2], p1, m_v[0]) >= 0.0f) { ++cr; } if (DelaunayGeometry.CrossProduct(m_v[2], p2, m_v[0]) >= 0.0f) { ++cr; } if (DelaunayGeometry.CrossProduct(m_v[2], p3, m_v[0]) >= 0.0f) { ++cr; } if (DelaunayGeometry.CrossProduct(m_v[2], p4, m_v[0]) >= 0.0f) { ++cr; } // There will be some sort intersection of triangle with rectangle if at least one point of // the rectangle is on, or to the right (not zero) of every segment of the triangle. if (ar != 0 && br != 0 && cr != 0) { return(true); } return(false); }
void Update(DelaunayPoint p) { List <Triangle> removeList = new List <Triangle>(); List <Triangle> visitedList = new List <Triangle>(); // Go in dfs order and keep adding triangles to it until the vertices of Triangle dont fall in the circumcircle m_currentTriangle.remove = true; m_currentTriangle.visited = true; removeList.Add(m_currentTriangle); for (int start = 0; start != removeList.Count; ++start) { // All triangles with circumcircle containing the point will need to be removed. Triangle remTriangle = removeList[start]; for (int k = 0; k < 3; k++) { Triangle adjacentTriangle = remTriangle.adjacentFace[k]; if (adjacentTriangle != null && !adjacentTriangle.visited) { adjacentTriangle.visited = true; if (adjacentTriangle.CircumCircleContains(p)) { adjacentTriangle.remove = true; removeList.Add(adjacentTriangle); //holds a list of removeable Triangle_t } else { visitedList.Add(adjacentTriangle); } } } } if (visitedList.Count > 0) { for (int i = 0; i < visitedList.Count; i++) { visitedList[i].visited = false; } } visitedList.Clear(); // For every n triangles we are going to remove we should be able to add n+2 new ones int numNewTriangles = 0; for (int i = 0; i != removeList.Count; i++) { Triangle remTriangle = removeList[i]; for (int j = 0; j != 3; j++) { // Create a Triangle for each side that isnt to be removed. if (remTriangle.adjacentFace[j] == null) { numNewTriangles++; } else if (!remTriangle.adjacentFace[j].remove) { numNewTriangles++; } } } // Paranoia check. if (numNewTriangles - 2 != removeList.Count) { // Don't expect to hit this, but checking anyways just in case of rounding errors. for (int i = 0; i != removeList.Count; i++) { removeList[i].visited = false; removeList[i].remove = false; } return; } // Create new triangles. List <Triangle> newList = new List <Triangle>(); int[] vertIndex = new int[] { 1, 2, 0 }; for (int i = 0; i != removeList.Count; i++) { Triangle remTriangle = removeList[i]; for (int j = 0; j < 3; j++) { //create a Triangle for each side that isnt to be removed Triangle adjacent = remTriangle.adjacentFace[j]; if (adjacent == null) { Triangle t = new Triangle(remTriangle.m_v[j], remTriangle.m_v[vertIndex[j]], p); newList.Add(t); } else if (!adjacent.remove) { Triangle t = new Triangle(remTriangle.m_v[j], remTriangle.m_v[vertIndex[j]], p); // Stitch shared edge of new triangle into existing network. t.adjacentFace[0] = adjacent; for (int e = 0; e != 3; e++) { if (adjacent.adjacentFace[e] == remTriangle) { adjacent.adjacentFace[e] = t; } } newList.Add(t); } } } // Stitch up the new triangles with each-other. Simplified case because vertex[2] for all shared triangles is the same, and is // in fact parameter point 'p'. m_currentTriangle = null; for (int i = 0; i != newList.Count; i++) { Triangle t = newList[i]; m_currentTriangle = t; // Iterate over other un-stitched edges looking for a match. for (int j = i + 1; (j != newList.Count) && ((t.adjacentFace[1] == null) || (t.adjacentFace[2] == null)); j++) { Triangle q = newList[j]; if (t.adjacentFace[1] == null) { if (t.m_v[1] == q.m_v[0]) { t.adjacentFace[1] = q; q.adjacentFace[2] = t; } } if (t.adjacentFace[2] == null) { if (t.m_v[0] == q.m_v[1]) { t.adjacentFace[2] = q; q.adjacentFace[1] = t; } } } } // Free triangles that were to be removed. for (int i = 0; i != removeList.Count; i++) { Triangle cur = removeList[i]; m_newTriangles.Remove(cur); FreeTriangle(cur, false); } // Add new triangles for later consideration & processing. for (int i = 0; i != newList.Count; ++i) { m_newTriangles.Add(newList[i]); } }
bool LocateInternalUsingTriangleList(IEnumerable<Triangle> triangles, DelaunayPoint p) { foreach(Triangle triangle in triangles) { if (LocateInternal(triangle, p) != null) return true; } return false; }
float SegmentsIntersect(DelaunayPoint a, DelaunayPoint b, DelaunayPoint c, DelaunayPoint d, double t) { //what if denominator is zero?? double diff0 = (c.Y - a.Y) * MULTIPLIER; double diff1 = (d.X - c.X) * MULTIPLIER; double diff2 = (a.X - c.X) * MULTIPLIER; double diff3 = (d.Y - c.Y) * MULTIPLIER; double diff4 = (b.Y - a.Y) * MULTIPLIER; double diff5 = (b.X - a.X) * MULTIPLIER; t = (diff0 * diff1 + diff2 * diff3) / (diff4 * diff1 - diff5 * diff3); double s = (-diff2 * diff4 - diff0 * diff5) /(diff3 * diff5 - diff1 * diff4); if(Math.Abs(t) <= VERY_SMALL_DIST) t = 0; if(Math.Abs(s) <= VERY_SMALL_DIST) s = 0; return (float)s; }
void Update(DelaunayPoint p) { List<Triangle> removeList = new List<Triangle>(); List<Triangle> visitedList = new List<Triangle>(); // Go in dfs order and keep adding triangles to it until the vertices of Triangle dont fall in the circumcircle m_currentTriangle.remove = true; m_currentTriangle.visited = true; removeList.Add(m_currentTriangle); for (int start = 0; start != removeList.Count; ++start) { // All triangles with circumcircle containing the point will need to be removed. Triangle remTriangle = removeList[start]; for(int k = 0; k < 3; k++) { Triangle adjacentTriangle = remTriangle.adjacentFace[k]; if(adjacentTriangle != null && !adjacentTriangle.visited ) { adjacentTriangle.visited = true; if(adjacentTriangle.CircumCircleContains(p)) { adjacentTriangle.remove = true; removeList.Add(adjacentTriangle); //holds a list of removeable Triangle_t } else { visitedList.Add(adjacentTriangle); } } } } if (visitedList.Count > 0) { for(int i = 0; i < visitedList.Count; i++) visitedList[i].visited = false; } visitedList.Clear(); // For every n triangles we are going to remove we should be able to add n+2 new ones int numNewTriangles = 0; for(int i = 0; i != removeList.Count; i++) { Triangle remTriangle = removeList[i]; for(int j = 0; j != 3; j++) { // Create a Triangle for each side that isnt to be removed. if(remTriangle.adjacentFace[j] == null) { numNewTriangles++; } else if(!remTriangle.adjacentFace[j].remove) { numNewTriangles++; } } } // Paranoia check. if(numNewTriangles - 2 != removeList.Count) { // Don't expect to hit this, but checking anyways just in case of rounding errors. for(int i = 0; i != removeList.Count; i++) { removeList[i].visited = false; removeList[i].remove = false; } return; } // Create new triangles. List<Triangle> newList = new List<Triangle>(); int[] vertIndex = new int[] { 1, 2, 0 }; for(int i = 0; i != removeList.Count; i++) { Triangle remTriangle = removeList[i]; for(int j = 0; j < 3; j++) { //create a Triangle for each side that isnt to be removed Triangle adjacent = remTriangle.adjacentFace[j]; if(adjacent == null) { Triangle t = new Triangle(remTriangle.m_v[j], remTriangle.m_v[vertIndex[j]], p); newList.Add(t); } else if(!adjacent.remove) { Triangle t = new Triangle(remTriangle.m_v[j], remTriangle.m_v[vertIndex[j]], p); // Stitch shared edge of new triangle into existing network. t.adjacentFace[0] = adjacent; for (int e = 0; e != 3; e++) { if (adjacent.adjacentFace[e] == remTriangle) adjacent.adjacentFace[e] = t; } newList.Add(t); } } } // Stitch up the new triangles with each-other. Simplified case because vertex[2] for all shared triangles is the same, and is // in fact parameter point 'p'. m_currentTriangle = null; for(int i = 0; i != newList.Count; i++) { Triangle t = newList[i]; m_currentTriangle = t; // Iterate over other un-stitched edges looking for a match. for(int j = i+1; (j != newList.Count) && ((t.adjacentFace[1] == null) || (t.adjacentFace[2] == null)); j++) { Triangle q = newList[j]; if (t.adjacentFace[1] == null) { if(t.m_v[1] == q.m_v[0]) { t.adjacentFace[1] = q; q.adjacentFace[2] = t; } } if (t.adjacentFace[2] == null) { if(t.m_v[0] == q.m_v[1]) { t.adjacentFace[2] = q; q.adjacentFace[1] = t; } } } } // Free triangles that were to be removed. for(int i = 0; i != removeList.Count; i++) { Triangle cur = removeList[i]; m_newTriangles.Remove(cur); FreeTriangle(cur, false); } // Add new triangles for later consideration & processing. for (int i = 0; i != newList.Count; ++i) m_newTriangles.Add(newList[i]); }
bool Overlaps(Extent2D extent) { // Check simplist case - triangle inside extent. if (extent.Contains(m_extent)) return true; // Use right-hand rule for each triangle segment against all points of extent rectangle. DelaunayPoint p1 = new DelaunayPoint(extent.MinX, extent.MinY, 0.0f, 0); DelaunayPoint p2 = new DelaunayPoint(extent.MaxX, extent.MinY, 0.0f, 0); DelaunayPoint p3 = new DelaunayPoint(extent.MaxX, extent.MaxY, 0.0f, 0); DelaunayPoint p4 = new DelaunayPoint(extent.MinX, extent.MaxY, 0.0f, 0); int ar = 0; if (DelaunayGeometry.CrossProduct(m_v[0], p1, m_v[1]) >= 0.0f) ++ar; if (DelaunayGeometry.CrossProduct(m_v[0], p2, m_v[1]) >= 0.0f) ++ar; if (DelaunayGeometry.CrossProduct(m_v[0], p3, m_v[1]) >= 0.0f) ++ar; if (DelaunayGeometry.CrossProduct(m_v[0], p4, m_v[1]) >= 0.0f) ++ar; int br = 0; if (DelaunayGeometry.CrossProduct(m_v[1], p1, m_v[2]) >= 0.0f) ++br; if (DelaunayGeometry.CrossProduct(m_v[1], p2, m_v[2]) >= 0.0f) ++br; if (DelaunayGeometry.CrossProduct(m_v[1], p3, m_v[2]) >= 0.0f) ++br; if (DelaunayGeometry.CrossProduct(m_v[1], p4, m_v[2]) >= 0.0f) ++br; int cr = 0; if (DelaunayGeometry.CrossProduct(m_v[2], p1, m_v[0]) >= 0.0f) ++cr; if (DelaunayGeometry.CrossProduct(m_v[2], p2, m_v[0]) >= 0.0f) ++cr; if (DelaunayGeometry.CrossProduct(m_v[2], p3, m_v[0]) >= 0.0f) ++cr; if (DelaunayGeometry.CrossProduct(m_v[2], p4, m_v[0]) >= 0.0f) ++cr; // There will be some sort intersection of triangle with rectangle if at least one point of // the rectangle is on, or to the right (not zero) of every segment of the triangle. if (ar != 0 && br != 0 && cr != 0) { return true; } return false; }
public bool IsCoincidentWithVertex(DelaunayPoint p) { double distA = (m_v[0].X - p.X) * (m_v[0].X - p.X) + (m_v[0].Y - p.Y) * (m_v[0].Y - p.Y); double distB = (m_v[1].X - p.X) * (m_v[1].X - p.X) + (m_v[1].Y - p.Y) * (m_v[1].Y - p.Y); double distC = (m_v[2].X - p.X) * (m_v[2].X - p.X) + (m_v[2].Y - p.Y) * (m_v[2].Y - p.Y); if((distA <= VERY_SMALL_DIST) || (distB <= VERY_SMALL_DIST) || (distC <= VERY_SMALL_DIST)) return true; return false; }
Triangle GetAdjacent(DelaunayPoint start, DelaunayPoint end) { double t = 0; double s = SegmentsIntersect(m_v[0], m_v[1], start, end, t); if(t >= 0 && t <= 1 && s >= 0 && s <= 1) { return adjacentFace[0]; } s = SegmentsIntersect(m_v[1], m_v[2], start, end, t); if(t >= 0 && t <= 1 && s >= 0 && s <= 1) { return adjacentFace[1]; } s = SegmentsIntersect(m_v[2], m_v[0], start, end, t); if(t >= 0 && t <= 1 && s >= 0 && s <= 1) { return adjacentFace[2]; } return null; }