From e29212329d763b81d52b3c322a3e4c05532eb58b Mon Sep 17 00:00:00 2001 From: "SND\\wo80_cp" Date: Tue, 18 Jun 2013 09:38:34 +0000 Subject: [PATCH] Added QuadTree for point location Added maximum angle to test app git-svn-id: https://triangle.svn.codeplex.com/svn@73189 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5 --- Triangle.NET/TestApp/FormMain.cs | 17 + .../TestApp/Views/AboutView.Designer.cs | 2 +- .../TestApp/Views/MeshControlView.Designer.cs | 107 +++-- Triangle.NET/TestApp/Views/MeshControlView.cs | 12 + Triangle.NET/Triangle/Tools/QuadTree.cs | 423 ++++++++++++++++++ Triangle.NET/Triangle/Triangle.csproj | 1 + 6 files changed, 529 insertions(+), 33 deletions(-) create mode 100644 Triangle.NET/Triangle/Tools/QuadTree.cs diff --git a/Triangle.NET/TestApp/FormMain.cs b/Triangle.NET/TestApp/FormMain.cs index c7b5f12..ae13757 100644 --- a/Triangle.NET/TestApp/FormMain.cs +++ b/Triangle.NET/TestApp/FormMain.cs @@ -452,6 +452,13 @@ namespace MeshExplorer mesh.Behavior.MinAngle = meshControlView.ParamMinAngleValue; + double maxAngle = meshControlView.ParamMaxAngleValue; + + if (maxAngle < 180) + { + mesh.Behavior.MaxAngle = maxAngle; + } + // Ignore area constraints on initial triangulation. //double area = slMaxArea.Value * 0.01; @@ -507,6 +514,13 @@ namespace MeshExplorer mesh.Behavior.MinAngle = meshControlView.ParamMinAngleValue; + double maxAngle = meshControlView.ParamMaxAngleValue; + + if (maxAngle < 180) + { + mesh.Behavior.MaxAngle = maxAngle; + } + try { sw.Start(); @@ -715,7 +729,10 @@ namespace MeshExplorer if (mesh != null) { bool isConsistent, isDelaunay; + + Behavior.Verbose = true; mesh.Check(out isConsistent, out isDelaunay); + Behavior.Verbose = false; ShowLog(); } diff --git a/Triangle.NET/TestApp/Views/AboutView.Designer.cs b/Triangle.NET/TestApp/Views/AboutView.Designer.cs index 2aa417f..a3d08e3 100644 --- a/Triangle.NET/TestApp/Views/AboutView.Designer.cs +++ b/Triangle.NET/TestApp/Views/AboutView.Designer.cs @@ -79,7 +79,7 @@ this.label19.Name = "label19"; this.label19.Size = new System.Drawing.Size(134, 40); this.label19.TabIndex = 6; - this.label19.Text = "Beta 3 (2013-01-20)\r\nChristian Woltering\r\nMIT"; + this.label19.Text = "Beta 3 (2013-06-18)\r\nChristian Woltering\r\nMIT"; // // label18 // diff --git a/Triangle.NET/TestApp/Views/MeshControlView.Designer.cs b/Triangle.NET/TestApp/Views/MeshControlView.Designer.cs index 7f4d56b..089f253 100644 --- a/Triangle.NET/TestApp/Views/MeshControlView.Designer.cs +++ b/Triangle.NET/TestApp/Views/MeshControlView.Designer.cs @@ -35,20 +35,23 @@ this.label9 = new System.Windows.Forms.Label(); this.label8 = new System.Windows.Forms.Label(); this.label5 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.lbMaxAngle = new System.Windows.Forms.Label(); + this.cbSweepline = new MeshExplorer.Controls.DarkCheckBox(); + this.slMaxAngle = new MeshExplorer.Controls.DarkSlider(); this.slMaxArea = new MeshExplorer.Controls.DarkSlider(); this.slMinAngle = new MeshExplorer.Controls.DarkSlider(); this.cbConformDel = new MeshExplorer.Controls.DarkCheckBox(); this.cbConvex = new MeshExplorer.Controls.DarkCheckBox(); this.cbQuality = new MeshExplorer.Controls.DarkCheckBox(); - this.cbSweepline = new MeshExplorer.Controls.DarkCheckBox(); - this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // lbMaxArea // this.lbMaxArea.AutoSize = true; this.lbMaxArea.ForeColor = System.Drawing.Color.White; - this.lbMaxArea.Location = new System.Drawing.Point(227, 65); + this.lbMaxArea.Location = new System.Drawing.Point(227, 87); this.lbMaxArea.Name = "lbMaxArea"; this.lbMaxArea.Size = new System.Drawing.Size(13, 13); this.lbMaxArea.TabIndex = 20; @@ -58,7 +61,7 @@ // this.label6.AutoSize = true; this.label6.ForeColor = System.Drawing.Color.White; - this.label6.Location = new System.Drawing.Point(8, 64); + this.label6.Location = new System.Drawing.Point(8, 86); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(81, 13); this.label6.TabIndex = 23; @@ -78,7 +81,7 @@ // this.label23.BackColor = System.Drawing.Color.DimGray; this.label23.ForeColor = System.Drawing.Color.DarkGray; - this.label23.Location = new System.Drawing.Point(8, 151); + this.label23.Location = new System.Drawing.Point(8, 173); this.label23.Name = "label23"; this.label23.Size = new System.Drawing.Size(251, 33); this.label23.TabIndex = 24; @@ -89,7 +92,7 @@ // this.label9.BackColor = System.Drawing.Color.DimGray; this.label9.ForeColor = System.Drawing.Color.DarkGray; - this.label9.Location = new System.Drawing.Point(8, 215); + this.label9.Location = new System.Drawing.Point(8, 237); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(258, 33); this.label9.TabIndex = 26; @@ -99,7 +102,7 @@ // this.label8.BackColor = System.Drawing.Color.DimGray; this.label8.ForeColor = System.Drawing.Color.DarkGray; - this.label8.Location = new System.Drawing.Point(8, 88); + this.label8.Location = new System.Drawing.Point(8, 110); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(258, 33); this.label8.TabIndex = 25; @@ -116,11 +119,66 @@ this.label5.TabIndex = 21; this.label5.Text = "Minimum angle"; // + // label1 + // + this.label1.BackColor = System.Drawing.Color.DimGray; + this.label1.ForeColor = System.Drawing.Color.DarkGray; + this.label1.Location = new System.Drawing.Point(8, 304); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(258, 33); + this.label1.TabIndex = 26; + this.label1.Text = "Use Sweepline algorithm for triangulation instead of default Divide && Conquer."; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.White; + this.label2.Location = new System.Drawing.Point(8, 64); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(88, 13); + this.label2.TabIndex = 21; + this.label2.Text = "Maximum angle"; + // + // lbMaxAngle + // + this.lbMaxAngle.AutoSize = true; + this.lbMaxAngle.ForeColor = System.Drawing.Color.White; + this.lbMaxAngle.Location = new System.Drawing.Point(227, 65); + this.lbMaxAngle.Name = "lbMaxAngle"; + this.lbMaxAngle.Size = new System.Drawing.Size(25, 13); + this.lbMaxAngle.TabIndex = 22; + this.lbMaxAngle.Text = "180"; + // + // cbSweepline + // + this.cbSweepline.BackColor = System.Drawing.Color.DimGray; + this.cbSweepline.Checked = false; + this.cbSweepline.Location = new System.Drawing.Point(11, 278); + this.cbSweepline.Name = "cbSweepline"; + this.cbSweepline.Size = new System.Drawing.Size(181, 23); + this.cbSweepline.TabIndex = 27; + this.cbSweepline.Text = "Use Sweepline algorithm"; + this.cbSweepline.UseVisualStyleBackColor = false; + // + // slMaxAngle + // + this.slMaxAngle.BackColor = System.Drawing.Color.Transparent; + this.slMaxAngle.CriticalPercent = ((uint)(89u)); + this.slMaxAngle.Location = new System.Drawing.Point(102, 61); + this.slMaxAngle.Maximum = 100; + this.slMaxAngle.Minimum = 0; + this.slMaxAngle.Name = "slMaxAngle"; + this.slMaxAngle.Size = new System.Drawing.Size(119, 18); + this.slMaxAngle.TabIndex = 18; + this.slMaxAngle.Text = "darkSlider1"; + this.slMaxAngle.Value = 0; + this.slMaxAngle.ValueChanging += new System.EventHandler(this.slMaxAngle_ValueChanging); + // // slMaxArea // this.slMaxArea.BackColor = System.Drawing.Color.Transparent; this.slMaxArea.CriticalPercent = ((uint)(0u)); - this.slMaxArea.Location = new System.Drawing.Point(102, 61); + this.slMaxArea.Location = new System.Drawing.Point(102, 83); this.slMaxArea.Maximum = 100; this.slMaxArea.Minimum = 0; this.slMaxArea.Name = "slMaxArea"; @@ -148,7 +206,7 @@ // this.cbConformDel.BackColor = System.Drawing.Color.DimGray; this.cbConformDel.Checked = false; - this.cbConformDel.Location = new System.Drawing.Point(11, 131); + this.cbConformDel.Location = new System.Drawing.Point(11, 153); this.cbConformDel.Name = "cbConformDel"; this.cbConformDel.Size = new System.Drawing.Size(142, 17); this.cbConformDel.TabIndex = 16; @@ -159,7 +217,7 @@ // this.cbConvex.BackColor = System.Drawing.Color.DimGray; this.cbConvex.Checked = false; - this.cbConvex.Location = new System.Drawing.Point(11, 195); + this.cbConvex.Location = new System.Drawing.Point(11, 217); this.cbConvex.Name = "cbConvex"; this.cbConvex.Size = new System.Drawing.Size(115, 17); this.cbConvex.TabIndex = 15; @@ -177,44 +235,26 @@ this.cbQuality.Text = "Quality mesh"; this.cbQuality.UseVisualStyleBackColor = false; // - // cbSweepline - // - this.cbSweepline.BackColor = System.Drawing.Color.DimGray; - this.cbSweepline.Checked = false; - this.cbSweepline.Location = new System.Drawing.Point(11, 260); - this.cbSweepline.Name = "cbSweepline"; - this.cbSweepline.Size = new System.Drawing.Size(187, 17); - this.cbSweepline.TabIndex = 15; - this.cbSweepline.Text = "Use Sweepline algorithm"; - this.cbSweepline.UseVisualStyleBackColor = false; - // - // label1 - // - this.label1.BackColor = System.Drawing.Color.DimGray; - this.label1.ForeColor = System.Drawing.Color.DarkGray; - this.label1.Location = new System.Drawing.Point(8, 280); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(258, 33); - this.label1.TabIndex = 26; - this.label1.Text = "Use Sweepline algorithm for triangulation instead of default Divide && Conquer."; - // // MeshControlView // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.DimGray; + this.Controls.Add(this.cbSweepline); this.Controls.Add(this.lbMaxArea); this.Controls.Add(this.label6); + this.Controls.Add(this.lbMaxAngle); this.Controls.Add(this.lbMinAngle); this.Controls.Add(this.label23); this.Controls.Add(this.label1); this.Controls.Add(this.label9); this.Controls.Add(this.label8); + this.Controls.Add(this.label2); this.Controls.Add(this.label5); + this.Controls.Add(this.slMaxAngle); this.Controls.Add(this.slMaxArea); this.Controls.Add(this.slMinAngle); this.Controls.Add(this.cbConformDel); - this.Controls.Add(this.cbSweepline); this.Controls.Add(this.cbConvex); this.Controls.Add(this.cbQuality); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -242,5 +282,8 @@ private Controls.DarkCheckBox cbQuality; private Controls.DarkCheckBox cbSweepline; private System.Windows.Forms.Label label1; + private Controls.DarkSlider slMaxAngle; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label lbMaxAngle; } } diff --git a/Triangle.NET/TestApp/Views/MeshControlView.cs b/Triangle.NET/TestApp/Views/MeshControlView.cs index dbb311c..4342350 100644 --- a/Triangle.NET/TestApp/Views/MeshControlView.cs +++ b/Triangle.NET/TestApp/Views/MeshControlView.cs @@ -43,6 +43,11 @@ namespace MeshExplorer.Views get { return (slMinAngle.Value * 40) / 100; } } + public int ParamMaxAngleValue + { + get { return 80 + (100 - slMaxAngle.Value); } + } + public double ParamMaxAreaValue { get { return slMaxArea.Value * 0.01; } @@ -55,6 +60,13 @@ namespace MeshExplorer.Views lbMinAngle.Text = angle.ToString(); } + private void slMaxAngle_ValueChanging(object sender, EventArgs e) + { + // Between 180 and 80 (step 1) + int angle = 80 + (100 - slMaxAngle.Value); + lbMaxAngle.Text = angle.ToString(); + } + private void slMaxArea_ValueChanging(object sender, EventArgs e) { // Between 0 and 1 (step 0.01) diff --git a/Triangle.NET/Triangle/Tools/QuadTree.cs b/Triangle.NET/Triangle/Tools/QuadTree.cs new file mode 100644 index 0000000..6b61549 --- /dev/null +++ b/Triangle.NET/Triangle/Tools/QuadTree.cs @@ -0,0 +1,423 @@ +// ----------------------------------------------------------------------- +// +// Original code by Frank Dockhorn, http://sourceforge.net/projects/quadtreesim/ +// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/ +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.Tools +{ + using System.Collections.Generic; + using System.Linq; + using TriangleNet.Geometry; + + /// + /// A Quadtree implementation optimised for triangles. + /// + public class QuadTree + { + QuadNode root; + + internal ITriangle[] triangles; + + internal int sizeBound; + internal int maxDepth; + + /// + /// Initializes a new instance of the class. + /// + /// Mesh containing triangles. + /// The maximum depth of the tree. + /// The maximum number of triangles contained in a leaf. + /// + /// The quadtree does not track changes of the mesh. If a mesh is refined or + /// changed in any other way, a new quadtree has to be built to make the point + /// location work. + /// + /// A node of the tree will be split, if its level if less than the max depth parameter + /// AND the number of triangles in the node is greater than the size bound. + /// + public QuadTree(Mesh mesh, int maxDepth = 10, int sizeBound = 10) + { + this.maxDepth = maxDepth; + this.sizeBound = sizeBound; + + triangles = mesh.Triangles.ToArray(); + + int currentDepth = 0; + + root = new QuadNode(mesh.Bounds, this, true); + root.CreateSubRegion(++currentDepth); + } + + public ITriangle Query(double x, double y) + { + var point = new Point(x, y); + var indices = root.FindTriangles(point); + + var result = new List(); + + foreach (var i in indices) + { + var tri = this.triangles[i]; + + if (IsPointInTriangle(point, tri.GetVertex(0), tri.GetVertex(1), tri.GetVertex(2))) + { + result.Add(tri); + } + } + + return result.FirstOrDefault(); + } + + /// + /// Test, if a given point lies inside a triangle. + /// + /// Point to locate. + /// Corner point of triangle. + /// Corner point of triangle. + /// Corner point of triangle. + /// True, if point is inside or on the edge of this triangle. + internal static bool IsPointInTriangle(Point p, Point t0, Point t1, Point t2) + { + // 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(p.X - t0.X, p.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; + } + + internal static double DotProduct(Point p, Point q) + { + return p.X * q.X + p.Y * q.Y; + } + } + + #region QuadNode class + + /// + /// A node of the quadtree. + /// + class QuadNode + { + const int SW = 0; + const int SE = 1; + const int NW = 2; + const int NE = 3; + + const double EPS = 1e-6; + + static readonly byte[] BITVECTOR = { 0x1, 0x2, 0x4, 0x8 }; + + BoundingBox bounds; + Point pivot; + QuadTree tree; + QuadNode[] regions; + List triangles; + + byte bitRegions; + + public QuadNode(BoundingBox box, QuadTree tree) + : this(box, tree, false) + { + } + + public QuadNode(BoundingBox box, QuadTree tree, bool init) + { + this.tree = tree; + + this.bounds = new BoundingBox(box.Xmin, box.Ymin, box.Xmax, box.Ymax); + this.pivot = new Point((box.Xmin + box.Xmax) / 2, (box.Ymin + box.Ymax) / 2); + + this.bitRegions = 0; + + this.regions = new QuadNode[4]; + this.triangles = new List(); + + if (init) + { + // Allocate memory upfront + triangles.Capacity = tree.triangles.Length; + + foreach (var tri in tree.triangles) + { + triangles.Add(tri.ID); + } + } + } + + public List FindTriangles(Point searchPoint) + { + int region = FindRegion(searchPoint); + if (regions[region] == null) + { + return triangles; + } + return regions[region].FindTriangles(searchPoint); + } + + 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.Xmin, bounds.Ymin, pivot.X, pivot.Y); + regions[0] = new QuadNode(box, tree); + + // 2. region south east + box = new BoundingBox(pivot.X, bounds.Ymin, bounds.Xmax, pivot.Y); + regions[1] = new QuadNode(box, tree); + + // 3. region north west + box = new BoundingBox(bounds.Xmin, pivot.Y, pivot.X, bounds.Ymax); + regions[2] = new QuadNode(box, tree); + + // 4. region north east + box = new BoundingBox(pivot.X, pivot.Y, bounds.Xmax, bounds.Ymax); + 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, tri.ID); + } + + for (int i = 0; i < 4; i++) + { + if (regions[i].triangles.Count > tree.sizeBound && currentDepth < tree.maxDepth) + { + regions[i].CreateSubRegion(currentDepth + 1); + } + } + } + + void AddTriangleToRegion(Point[] triangle, int index) + { + bitRegions = 0; + if (QuadTree.IsPointInTriangle(pivot, triangle[0], triangle[1], triangle[2])) + { + AddToRegion(index, SW); + AddToRegion(index, SE); + AddToRegion(index, NW); + AddToRegion(index, NE); + return; + } + + FindTriangleIntersections(triangle, index); + + if (bitRegions == 0) + { + // we didn't find any intersection so we add this triangle to a point's region + int region = FindRegion(triangle[0]); + regions[region].triangles.Add(index); + } + } + + void FindTriangleIntersections(Point[] triangle, int index) + { + // PLEASE NOTE: Handling of component comparison is tightly associated with the implementation + // of the findRegion() function. That means when the point to be compared equals + // the pivot point the triangle must be put at least into region 2. + // Linear equations are in parametric form. + // m_pivot.dx = triangle[0].dx + t * (triangle[1].dx - triangle[0].dx) + // m_pivot.dy = triangle[0].dy + t * (triangle[1].dy - triangle[0].dy) + + int k = 2; + + double dx, dy; + // Iterate through all triangle laterals and find bounding box intersections + for (int i = 0; i < 3; k = i++) + { + dx = triangle[i].X - triangle[k].X; + dy = triangle[i].Y - triangle[k].Y; + + if (dx != 0.0) + { + FindIntersectionsWithX(dx, dy, triangle, index, k); + } + if (dy != 0.0) + { + FindIntersectionsWithY(dx, dy, triangle, index, k); + } + } + } + + void FindIntersectionsWithX(double dx, double dy, Point[] triangle, int index, int k) + { + // find intersection with plane x = m_pivot.dX + double t = (pivot.X - triangle[k].X) / dx; + + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double yComponent = triangle[k].Y + t * dy; + + if (yComponent < pivot.Y) + { + if (yComponent >= bounds.Ymin) + { + AddToRegion(index, SW); + AddToRegion(index, SE); + } + } + else if (yComponent <= bounds.Ymax) + { + AddToRegion(index, NW); + AddToRegion(index, NE); + } + } + // find intersection with plane x = m_boundingBox[0].dX + t = (bounds.Xmin - triangle[k].X) / dx; + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double yComponent = triangle[k].Y + t * dy; + + if (yComponent <= pivot.Y && yComponent >= bounds.Ymin) + { + AddToRegion(index, SW); + } + else if (yComponent >= pivot.Y && yComponent <= bounds.Ymax) + { + AddToRegion(index, NW); + } + } + // find intersection with plane x = m_boundingBox[1].dX + t = (bounds.Xmax - triangle[k].X) / dx; + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double yComponent = triangle[k].Y + t * dy; + + if (yComponent <= pivot.Y && yComponent >= bounds.Ymin) + { + AddToRegion(index, SE); + } + else if (yComponent >= pivot.Y && yComponent <= bounds.Ymax) + { + AddToRegion(index, NE); + } + } + } + + void FindIntersectionsWithY(double dx, double dy, Point[] triangle, int index, int k) + { + // find intersection with plane y = m_pivot.dY + double t = (pivot.Y - triangle[k].Y) / (dy); + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double xComponent = triangle[k].X + t * (dy); + + if (xComponent > pivot.X) + { + if (xComponent <= bounds.Xmax) + { + AddToRegion(index, SE); + AddToRegion(index, NE); + } + } + else if (xComponent >= bounds.Xmin) + { + AddToRegion(index, SW); + AddToRegion(index, NW); + } + } + // find intersection with plane y = m_boundingBox[0].dY + t = (bounds.Ymin - triangle[k].Y) / dy; + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double xComponent = triangle[k].X + t * dx; + + if (xComponent <= pivot.X && xComponent >= bounds.Xmin) + { + AddToRegion(index, SW); + } + else if (xComponent >= pivot.X && xComponent <= bounds.Xmax) + { + AddToRegion(index, SE); + } + } + // find intersection with plane y = m_boundingBox[1].dY + t = (bounds.Ymax - triangle[k].Y) / dy; + if (t < (1 + EPS) && t > -EPS) + { + // we have an intersection + double xComponent = triangle[k].X + t * dx; + + if (xComponent <= pivot.X && xComponent >= bounds.Xmin) + { + AddToRegion(index, NW); + } + else if (xComponent >= pivot.X && xComponent <= bounds.Xmax) + { + AddToRegion(index, NE); + } + } + } + + int FindRegion(Point point) + { + int b = 2; + if (point.Y < pivot.Y) + { + b = 0; + } + if (point.X > pivot.X) + { + b++; + } + return b; + } + + void AddToRegion(int index, int region) + { + //if (!(m_bitRegions & BITVECTOR[region])) + if ((bitRegions & BITVECTOR[region]) == 0) + { + regions[region].triangles.Add(index); + bitRegions |= BITVECTOR[region]; + } + } + } + + #endregion +} diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj index 8bbca83..c73b25b 100644 --- a/Triangle.NET/Triangle/Triangle.csproj +++ b/Triangle.NET/Triangle/Triangle.csproj @@ -87,6 +87,7 @@ +