public void CreateSubRegion(int currentDepth) { BoundingBox boundingBox = new BoundingBox(this.bounds.Xmin, this.bounds.Ymin, this.pivot.X, this.pivot.Y); this.regions[0] = new QuadNode(boundingBox, this.tree); boundingBox = new BoundingBox(this.pivot.X, this.bounds.Ymin, this.bounds.Xmax, this.pivot.Y); this.regions[1] = new QuadNode(boundingBox, this.tree); boundingBox = new BoundingBox(this.bounds.Xmin, this.pivot.Y, this.pivot.X, this.bounds.Ymax); this.regions[2] = new QuadNode(boundingBox, this.tree); boundingBox = new BoundingBox(this.pivot.X, this.pivot.Y, this.bounds.Xmax, this.bounds.Ymax); this.regions[3] = new QuadNode(boundingBox, this.tree); Point[] vertex = new Point[3]; foreach (int triangle in this.triangles) { ITriangle triangle1 = this.tree.triangles[triangle]; vertex[0] = triangle1.GetVertex(0); vertex[1] = triangle1.GetVertex(1); vertex[2] = triangle1.GetVertex(2); this.AddTriangleToRegion(vertex, triangle1.ID); } for (int i = 0; i < 4; i++) { if (this.regions[i].triangles.Count > this.tree.sizeBound && currentDepth < this.tree.maxDepth) { this.regions[i].CreateSubRegion(currentDepth + 1); } } }
/// <summary> /// Linear interpolation of a scalar value. /// </summary> /// <param name="p">The interpolation point.</param> /// <param name="triangle">The triangle containing the point.</param> /// <remarks> /// The point is expected to lie inside the triangle. /// </remarks> public static void InterpolateZ(Point p, ITriangle triangle) { Vertex org = triangle.GetVertex(0); Vertex dest = triangle.GetVertex(1); Vertex apex = triangle.GetVertex(2); float xdo, ydo, xao, yao; float denominator; float dx, dy; float xi, eta; // Compute the circumcenter of the triangle. xdo = dest.x - org.x; ydo = dest.y - org.y; xao = apex.x - org.x; yao = apex.y - org.y; denominator = 0.5 / (xdo * yao - xao * ydo); //dx = (yao * dodist - ydo * aodist) * denominator; //dy = (xdo * aodist - xao * dodist) * denominator; dx = p.x - org.x; dy = p.y - org.y; // To interpolate z value for the given point inserted, define a // coordinate system with a xi-axis, directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. xi = (yao * dx - xao * dy) * (2.0 * denominator); eta = (xdo * dy - ydo * dx) * (2.0 * denominator); p.z = org.z + xi * (dest.z - org.z) + eta * (apex.z - org.z); }
/// <summary> /// Linear interpolation of a scalar value. /// </summary> /// <param name="p">The interpolation point.</param> /// <param name="triangle">The triangle containing the point.</param> /// <remarks> /// The point is expected to lie inside the triangle. /// </remarks> public static void InterpolateZ(Point p, ITriangle triangle) { var org = triangle.GetVertex(0); var dest = triangle.GetVertex(1); var apex = triangle.GetVertex(2); // Compute the circumcenter of the triangle. double xdo = dest.x - org.x; double ydo = dest.y - org.y; double xao = apex.x - org.x; double yao = apex.y - org.y; double denominator = 0.5 / (xdo * yao - xao * ydo); double dx = p.x - org.x; double dy = p.y - org.y; // To interpolate z value for the given point inserted, define a // coordinate system with a xi-axis, directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. double xi = (yao * dx - xao * dy) * (2.0 * denominator); double eta = (xdo * dy - ydo * dx) * (2.0 * denominator); p.z = org.z + xi * (dest.z - org.z) + eta * (apex.z - org.z); }
/// <summary> /// Linear interpolation of a point. /// </summary> /// <param name="tri">The triangle containing the point <paramref name="p"/></param> /// <param name="p">The point to interpolate.</param> /// <param name="data">The vertex data (z values).</param> /// <returns>The linear interpolation value.</returns> /// <remarks> /// IMPORTANT: this method assumes the mesh vertex ids correspond to the data array indices. /// </remarks> public static double InterpolatePoint(ITriangle tri, Point p, double[] data) { var org = tri.GetVertex(0); var dest = tri.GetVertex(1); var apex = tri.GetVertex(2); double xdo = dest.x - org.x; double ydo = dest.y - org.y; double xao = apex.x - org.x; double yao = apex.y - org.y; double denominator = 0.5 / (xdo * yao - xao * ydo); double dx = p.x - org.x; double dy = p.y - org.y; // To interpolate z value for the given point inserted, define a // coordinate system with a xi-axis, directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. double xi = (yao * dx - xao * dy) * (2.0 * denominator); double eta = (xdo * dy - ydo * dx) * (2.0 * denominator); double orgz = data[org.id]; return(orgz + xi * (data[dest.id] - orgz) + eta * (data[apex.id] - orgz)); }
/// <summary> /// Linear interpolation of a scalar value. /// </summary> /// <param name="p">The interpolation point.</param> /// <param name="triangle">The triangle containing the point.</param> /// <remarks> /// The point is expected to lie inside the triangle. /// </remarks> public static void InterpolateZ(Point p, ITriangle triangle) { Vertex org = triangle.GetVertex(0); Vertex dest = triangle.GetVertex(1); Vertex apex = triangle.GetVertex(2); double xdo, ydo, xao, yao; double denominator; double dx, dy; double xi, eta; // Compute the circumcenter of the triangle. xdo = dest.x - org.x; ydo = dest.y - org.y; xao = apex.x - org.x; yao = apex.y - org.y; denominator = 0.5 / (xdo * yao - xao * ydo); //dx = (yao * dodist - ydo * aodist) * denominator; //dy = (xdo * aodist - xao * dodist) * denominator; dx = p.x - org.x; dy = p.y - org.y; // To interpolate z value for the given point inserted, define a // coordinate system with a xi-axis, directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. xi = (yao * dx - xao * dy) * (2.0 * denominator); eta = (xdo * dy - ydo * dx) * (2.0 * denominator); p.z = org.z + xi * (dest.z - org.z) + eta * (apex.z - org.z); }
/// <summary> /// Linear interpolation of vertex attributes. /// </summary> /// <param name="vertex">The interpolation vertex.</param> /// <param name="triangle">The triangle containing the vertex.</param> /// <param name="n">The number of vertex attributes.</param> /// <remarks> /// The vertex is expected to lie inside the triangle. /// </remarks> public static void InterpolateAttributes(Vertex vertex, ITriangle triangle, int n) { var org = triangle.GetVertex(0); var dest = triangle.GetVertex(1); var apex = triangle.GetVertex(2); double xdo = dest.x - org.x; double ydo = dest.y - org.y; double xao = apex.x - org.x; double yao = apex.y - org.y; double denominator = 0.5 / (xdo * yao - xao * ydo); double dx = vertex.x - org.x; double dy = vertex.y - org.y; // To interpolate vertex attributes for the new vertex, define a // coordinate system with a xi-axis directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. double xi = (yao * dx - xao * dy) * (2.0 * denominator); double eta = (xdo * dy - ydo * dx) * (2.0 * denominator); for (int i = 0; i < n; i++) { // Interpolate the vertex attributes. vertex.attributes[i] = org.attributes[i] + xi * (dest.attributes[i] - org.attributes[i]) + eta * (apex.attributes[i] - org.attributes[i]); } }
private double CalculateSquareOfTriangle(ITriangle triangle) { Vertex A = triangle.GetVertex(0); Vertex B = triangle.GetVertex(1); Vertex C = triangle.GetVertex(2); return(Math.Abs((A.X * (B.Y - C.Y) + B.X * (C.Y - A.Y) + C.X * (A.Y - B.Y)) / 2)); }
private Point GetIncenter(ITriangle triangle) { Point incenter = new Point(); Vertex A = triangle.GetVertex(0), B = triangle.GetVertex(1), C = triangle.GetVertex(2); double a = GetLength(B, C), b = GetLength(A, C), c = GetLength(A, B); double p = a + b + c; incenter.X = (a * A.X + b * B.X + c * C.X) / p; incenter.Y = (a * A.Y + b * B.Y + c * C.Y) / p; return(incenter); }
public void CreateSubRegion(int currentDepth) { // The four sub regions of the quad tree // +--------------+ // | nw 2 | ne 3 | // |------+pivot--| // | sw 0 | se 1 | // +--------------+ Rectangle box; var width = bounds.Right - pivot.x; var height = bounds.Top - pivot.y; // 1. region south west box = new Rectangle(bounds.Left, bounds.Bottom, width, height); regions[0] = new QuadNode(box, tree); // 2. region south east box = new Rectangle(pivot.x, bounds.Bottom, width, height); regions[1] = new QuadNode(box, tree); // 3. region north west box = new Rectangle(bounds.Left, pivot.y, width, height); regions[2] = new QuadNode(box, tree); // 4. region north east box = new Rectangle(pivot.x, pivot.y, width, height); regions[3] = new QuadNode(box, tree); Point[] triangle = new Point[3]; // Find region for every triangle vertex foreach (var index in triangles) { ITriangle tri = tree.triangles[index]; triangle[0] = tri.GetVertex(0); triangle[1] = tri.GetVertex(1); triangle[2] = tri.GetVertex(2); AddTriangleToRegion(triangle, index); } for (int i = 0; i < 4; i++) { if (regions[i].triangles.Count > tree.sizeBound && currentDepth < tree.maxDepth) { regions[i].CreateSubRegion(currentDepth + 1); } } }
static bool MaxEdgeLength(ITriangle tri, double area) { var p0 = tri.GetVertex(0); var p1 = tri.GetVertex(1); var p2 = tri.GetVertex(2); var s1 = DistSqr(p0, p1); var s2 = DistSqr(p1, p2); var s3 = DistSqr(p2, p0); // Comparing against squared max leg length. var maxlen = MAX_EDGE_LENGTH * MAX_EDGE_LENGTH; return(s1 > maxlen || s2 > maxlen || s3 > maxlen); }
private static double GetTriangleSquare(ITriangle triangle) { var matrixForSquare = new double[3, 3]; for (var i = 0; i < 3; i++) { matrixForSquare[i, 0] = 1; matrixForSquare[i, 1] = triangle.GetVertex(i).X; matrixForSquare[i, 2] = triangle.GetVertex(i).Y; } var determinant = DenseMatrix.OfArray(matrixForSquare).Determinant(); var square = 0.5 * determinant; return(square); }
public void CreateSubRegion(int currentDepth) { // The four sub regions of the quad tree // +--------------+ // | nw | ne | // |------+pivot--| // | sw | se | // +--------------+ BoundingBox box; // 1. region south west box = new BoundingBox(bounds.MinX, bounds.MinY, pivot.X, pivot.Y); regions[0] = new QuadNode(box, tree); // 2. region south east box = new BoundingBox(pivot.X, bounds.MinY, bounds.MaxX, pivot.Y); regions[1] = new QuadNode(box, tree); // 3. region north west box = new BoundingBox(bounds.MinX, pivot.Y, pivot.X, bounds.MaxY); regions[2] = new QuadNode(box, tree); // 4. region north east box = new BoundingBox(pivot.X, pivot.Y, bounds.MaxX, bounds.MaxY); regions[3] = new QuadNode(box, tree); Point[] triangle = new Point[3]; // Find region for every triangle vertex foreach (var index in triangles) { ITriangle tri = tree.triangles[index]; triangle[0] = tri.GetVertex(0); triangle[1] = tri.GetVertex(1); triangle[2] = tri.GetVertex(2); AddTriangleToRegion(triangle, index); } for (int i = 0; i < 4; i++) { if (regions[i].triangles.Count > tree.sizeBound && currentDepth < tree.maxDepth) { regions[i].CreateSubRegion(currentDepth + 1); } } }
public ITriangle Query(double x, double y) { Point point = new Point(x, y); List <int> nums = this.root.FindTriangles(point); List <ITriangle> triangles = new List <ITriangle>(); foreach (int num in nums) { ITriangle triangle = this.triangles[num]; if (!QuadTree.IsPointInTriangle(point, triangle.GetVertex(0), triangle.GetVertex(1), triangle.GetVertex(2))) { continue; } triangles.Add(triangle); } return(triangles.FirstOrDefault <ITriangle>()); }
/// <summary> /// Returns the bounding box of the triangle. /// </summary> /// <param name="triangle">Triangle instance.</param> /// <returns></returns> public static Rectangle Bounds(this ITriangle triangle) { var bounds = new Rectangle(); for (int i = 0; i < 3; i++) { bounds.Expand(triangle.GetVertex(i)); } return(bounds); }
/// <summary> /// Linear interpolation of vertex attributes. /// </summary> /// <param name="vertex">The interpolation vertex.</param> /// <param name="triangle">The triangle containing the vertex.</param> /// <param name="n">The number of vertex attributes.</param> /// <remarks> /// The vertex is expected to lie inside the triangle. /// </remarks> public static void InterpolateAttributes(Vertex vertex, ITriangle triangle, int n) { Vertex org = triangle.GetVertex(0); Vertex dest = triangle.GetVertex(1); Vertex apex = triangle.GetVertex(2); double xdo, ydo, xao, yao; double denominator; double dx, dy; double xi, eta; // Compute the circumcenter of the triangle. xdo = dest.x - org.x; ydo = dest.y - org.y; xao = apex.x - org.x; yao = apex.y - org.y; denominator = 0.5 / (xdo * yao - xao * ydo); //dx = (yao * dodist - ydo * aodist) * denominator; //dy = (xdo * aodist - xao * dodist) * denominator; dx = vertex.x - org.x; dy = vertex.y - org.y; // To interpolate vertex attributes for the new vertex inserted at // the circumcenter, define a coordinate system with a xi-axis, // directed from the triangle's origin to its destination, and // an eta-axis, directed from its origin to its apex. // Calculate the xi and eta coordinates of the circumcenter. xi = (yao * dx - xao * dy) * (2.0 * denominator); eta = (xdo * dy - ydo * dx) * (2.0 * denominator); for (int i = 0; i < n; i++) { // Interpolate the vertex attributes. vertex.attributes[i] = org.attributes[i] + xi * (dest.attributes[i] - org.attributes[i]) + eta * (apex.attributes[i] - org.attributes[i]); } }
private void DrawTriangle(ITriangle triangle) { var k = 80.0; System.Windows.Point p1 = new System.Windows.Point { X = k * triangle.GetVertex(0).X + 250.0, Y = k * triangle.GetVertex(0).Y + 100.0 }; System.Windows.Point p2 = new System.Windows.Point { X = k * triangle.GetVertex(1).X + 250.0, Y = k * triangle.GetVertex(1).Y + 100.0 }; System.Windows.Point p3 = new System.Windows.Point { X = k * triangle.GetVertex(2).X + 250.0, Y = k * triangle.GetVertex(2).Y + 100.0 }; DrawableTriangle myTriangle = new DrawableTriangle { Points = new List <System.Windows.Point> { p1, p2, p3 }, }; myTriangle.Stroke = Brushes.Black; myTriangle.StrokeThickness = 0.2; MainCanvas.Children.Add(myTriangle); }
/// <summary> /// Linear interpolation of vertex attributes. /// </summary> /// <param name="vertex">The interpolation vertex.</param> /// <param name="triangle">The triangle containing the vertex.</param> /// <param name="n">The number of vertex attributes.</param> /// <remarks> /// The vertex is expected to lie inside the triangle. /// </remarks> public static void InterpolateAttributes(Vertex vertex, ITriangle triangle, int n) { Vertex org = triangle.GetVertex(0); Vertex dest = triangle.GetVertex(1); Vertex apex = triangle.GetVertex(2); float xdo, ydo, xao, yao; float denominator; float dx, dy; float xi, eta; // Compute the circumcenter of the triangle. xdo = dest.x - org.x; ydo = dest.y - org.y; xao = apex.x - org.x; yao = apex.y - org.y; denominator = 0.5 / (xdo * yao - xao * ydo); //dx = (yao * dodist - ydo * aodist) * denominator; //dy = (xdo * aodist - xao * dodist) * denominator; dx = vertex.x - org.x; dy = vertex.y - org.y; // To interpolate vertex attributes for the new vertex, define a // coordinate system with a xi-axis directed from the triangle's // origin to its destination, and an eta-axis, directed from its // origin to its apex. xi = (yao * dx - xao * dy) * (2.0 * denominator); eta = (xdo * dy - ydo * dx) * (2.0 * denominator); for (int i = 0; i < n; i++) { // Interpolate the vertex attributes. vertex.attributes[i] = org.attributes[i] + xi * (dest.attributes[i] - org.attributes[i]) + eta * (apex.attributes[i] - org.attributes[i]); } }
/// <summary> /// Test whether a given point lies inside a triangle or not. /// </summary> /// <param name="triangle">Triangle instance.</param> /// <param name="x">Point to locate.</param> /// <param name="y">Point to locate.</param> /// <returns>True, if point is inside or on the edge of this triangle.</returns> public static bool Contains(this ITriangle triangle, double x, double y) { var t0 = triangle.GetVertex(0); var t1 = triangle.GetVertex(1); var t2 = triangle.GetVertex(2); // TODO: no need to create new Point instances here Point d0 = new Point(t1.X - t0.X, t1.Y - t0.Y); Point d1 = new Point(t2.X - t0.X, t2.Y - t0.Y); Point d2 = new Point(x - t0.X, y - t0.Y); // crossproduct of (0, 0, 1) and d0 Point c0 = new Point(-d0.Y, d0.X); // crossproduct of (0, 0, 1) and d1 Point c1 = new Point(-d1.Y, d1.X); // Linear combination d2 = s * d0 + v * d1. // // Multiply both sides of the equation with c0 and c1 // and solve for s and v respectively // // s = d2 * c1 / d0 * c1 // v = d2 * c0 / d1 * c0 double s = DotProduct(d2, c1) / DotProduct(d0, c1); double v = DotProduct(d2, c0) / DotProduct(d1, c0); if (s >= 0 && v >= 0 && ((s + v) <= 1)) { // Point is inside or on the edge of this triangle. return(true); } return(false); }
private bool TriangleContainsPoint(ITriangle triangle, float x, float y) { bool t1, t2, t3; t1 = Sign(x, y, triangle.GetVertex(0), triangle.GetVertex(1)) < 0.0; t2 = Sign(x, y, triangle.GetVertex(1), triangle.GetVertex(2)) < 0.0; t3 = Sign(x, y, triangle.GetVertex(2), triangle.GetVertex(0)) < 0.0; return((t1 == t2) && (t2 == t3)); }
private List <Vertex[]> GetOpenEdges(ITriangle triangle) { List <ITriangle> neighbours = new List <ITriangle>(); for (int i = 0; i < 3; i++) { if (triangle.GetNeighbor(i) != null) { neighbours.Add(triangle.GetNeighbor(i)); } } List <Vertex[]> openEdges = new List <Vertex[]>() { new Vertex[2] { triangle.GetVertex(0), triangle.GetVertex(1) }, new Vertex[2] { triangle.GetVertex(1), triangle.GetVertex(2) }, new Vertex[2] { triangle.GetVertex(2), triangle.GetVertex(0) }, }; foreach (var neighbour in neighbours) { List <Vertex[]> neighbourEdges = new List <Vertex[]>() { new Vertex[2] { neighbour.GetVertex(0), neighbour.GetVertex(1) }, new Vertex[2] { neighbour.GetVertex(1), neighbour.GetVertex(2) }, new Vertex[2] { neighbour.GetVertex(2), neighbour.GetVertex(0) }, }; List <int> edgesToRemove = new List <int>(); for (int i = 0; i < openEdges.Count; i++) { for (int j = 0; j < neighbourEdges.Count; j++) { if (openEdges[i][0] == neighbourEdges[j][0] && openEdges[i][1] == neighbourEdges[j][1] || openEdges[i][0] == neighbourEdges[j][1] && openEdges[i][1] == neighbourEdges[j][0]) { edgesToRemove.Add(i); } } } for (int i = 0; i < edgesToRemove.Count; i++) { openEdges.RemoveAt(edgesToRemove[i] - i); } } return(openEdges); }
private PointF GetPoint(ITriangle tri, int index) { var v = tri.GetVertex(index); return new PointF((float)v.X, (float)v.Y); }
/// <summary> /// Compute angle information for given triangle. /// </summary> /// <param name="triangle">The triangle to check.</param> /// <param name="data">Array of doubles (length 6).</param> /// <remarks> /// On return, the squared cosines of the minimum and maximum angle will /// be stored at position data[0] and data[1] respectively. /// If the triangle was obtuse, data[2] will be set to -1 and maximum angle /// is computed as (pi - acos(sqrt(data[1]))). /// </remarks> public static void ComputeAngles(ITriangle triangle, double[] data) { double min = 0.0; double max = 1.0; var va = triangle.GetVertex(0); var vb = triangle.GetVertex(1); var vc = triangle.GetVertex(2); double dxa = vb.x - vc.x; double dya = vb.y - vc.y; double lena = dxa * dxa + dya * dya; double dxb = vc.x - va.x; double dyb = vc.y - va.y; double lenb = dxb * dxb + dyb * dyb; double dxc = va.x - vb.x; double dyc = va.y - vb.y; double lenc = dxc * dxc + dyc * dyc; // Dot products. double dota = data[0] = dxb * dxc + dyb * dyc; double dotb = data[1] = dxc * dxa + dyc * dya; double dotc = data[2] = dxa * dxb + dya * dyb; // Squared cosines. data[3] = (dota * dota) / (lenb * lenc); data[4] = (dotb * dotb) / (lenc * lena); data[5] = (dotc * dotc) / (lena * lenb); // The sign of the dot product will tell us, if the angle is // acute (value < 0) or obtuse (value > 0). bool acute = true; double cos, dot; for (int i = 0; i < 3; i++) { dot = data[i]; cos = data[3 + i]; if (dot <= 0.0) { if (cos > min) { min = cos; } if (acute && (cos < max)) { max = cos; } } else { // Update max angle for (possibly non-acute) triangle if (acute || (cos > max)) { max = cos; acute = false; } } } data[0] = min; data[1] = max; data[2] = acute ? 1.0 : -1.0; }
private PointF GetPoint(ITriangle tri, int index) { var v = tri.GetVertex(index); return(new PointF((float)v.X, (float)v.Y)); }