public void TestBaseCaseTriangle()
            {
                List <Point> triangleInPositiveOrientation = new List <Point>()
                {
                    new Point(0, 0), new Point(1, 0), new Point(0, 1)
                };

                Int32Collection indices = SweepLinePolygonTriangulator.Triangulate(triangleInPositiveOrientation);

                Assert.That(indices.Count == 3);
                Assert.That(indices[0] == 0);
                Assert.That(indices[1] == 1);
                Assert.That(indices[2] == 2);


                List <Point> triangleInNegativeOrientation = new List <Point>()
                {
                    new Point(0, 0), new Point(0, 1), new Point(1, 0)
                };

                indices = SweepLinePolygonTriangulator.Triangulate(triangleInNegativeOrientation);
                Assert.That(indices.Count == 3);
                Assert.That(indices[0] == 0);
                Assert.That(indices[1] == 2);
                Assert.That(indices[2] == 1);
            }
Beispiel #2
0
        private static void CreateSimpleTriangulatedMesh(MeshBuilder meshBuilder)
        {
            List <Point> triangleInPositiveOrientation = new List <Point>()
            {
                new Point(0, 0),
                new Point(1, 0),
                new Point(0, 1)
            };
            //it's up to the user how to map 2D points to 3D, in this case we simply add a z-coordinate to the points:
            IEnumerable <Point3D> triangleInXYPlane = triangleInPositiveOrientation.Select(p => new Point3D(p.X, p.Y, 0));

            foreach (Point3D point in triangleInXYPlane)
            {
                meshBuilder.Positions.Add(point);
            }

            Int32Collection indices = SweepLinePolygonTriangulator.Triangulate(triangleInPositiveOrientation);

            foreach (int index in indices)
            {
                meshBuilder.TriangleIndices.Add(index);
            }

            //Create a triangle with the reversed orientation, this should thus also be visible from the other side:
            List <Point> triangleInNegativeOrientation = new List <Point>()
            {
                new Point(0, 0),
                new Point(0, 1),
                new Point(1, 0)
            };

            triangleInXYPlane = triangleInPositiveOrientation.Select(p => new Point3D(p.X, p.Y, 1));
            foreach (Point3D point in triangleInXYPlane)
            {
                meshBuilder.Positions.Add(point);
            }


            indices = SweepLinePolygonTriangulator.Triangulate(triangleInNegativeOrientation);
            foreach (int index in indices)
            {
                //add 3 as we have already added a triangle before, making the starting index of this triangle 3 higher:
                meshBuilder.TriangleIndices.Add(index + 3);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Add Points of a Hole to the PolygonData
        /// </summary>
        /// <param name="points">The Points that define the Hole in the Polygon</param>
        internal void AddHole(List <Point> points)
        {
            // Make Hole Clockwise
            if (SweepLinePolygonTriangulator.IsCCW(points))
            {
                points.Reverse();
            }
            // The Hole Points
            var polyPoints = points.Select(p => new PolygonPoint(p)).ToList();

            // If Endpoint equals Startpoint
            if (polyPoints[0].Equals(polyPoints[polyPoints.Count - 1]))
            {
                polyPoints.RemoveAt(polyPoints.Count - 1);
            }
            mHoles.Add(polyPoints);

            var cntBefore  = mPoints.Count;
            var pointCount = points.Count;

            // Add the PolygonPoints for this Polygon Object
            mPoints.AddRange(polyPoints);

            // Add the Indices
            for (int i = cntBefore; i < mPoints.Count; i++)
            {
                polyPoints[i - cntBefore].Index = i;
            }

            // Add Edges between the Points (to be able to navigate along the Polygon easily later)
            var cnt = mPoints.Count;

            for (int i = 0; i < pointCount; i++)
            {
                var lastIdx = (i + pointCount - 1) % pointCount;
                var edge    = new PolygonEdge(polyPoints[lastIdx], polyPoints[i]);
                polyPoints[lastIdx].EdgeTwo = edge;
                polyPoints[i].EdgeOne       = edge;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Generate a simple Polygon and then triangulate it.
        /// The Result is then Displayed.
        /// </summary>
        /// <param name="sender">The Sender (i.e. the Button)</param>
        /// <param name="e">The routet Event Args</param>
        private void generatePolygonButton_Click(object sender, RoutedEventArgs e)
        {
            // Generate random Polygon
            var random = new Random();
            var cnt    = mViewModel.PointCount;

            mPolygonPoints = new List <Vector2>();
            var angle     = 0f;
            var angleDiff = 2f * (Single)Math.PI / cnt;
            var radius    = 4f;
            // Random Radii for the Polygon
            var radii      = new List <float>();
            var innerRadii = new List <float>();

            for (int i = 0; i < cnt; i++)
            {
                radii.Add(random.NextFloat(radius * 0.9f, radius * 1.1f));
                innerRadii.Add(random.NextFloat(radius * 0.2f, radius * 0.3f));
            }
            var hole1        = new List <Vector2>();
            var hole2        = new List <Vector2>();
            var holeDistance = 2f;
            var holeAngle    = random.NextFloat(0, (float)Math.PI * 2);
            var cos          = (float)Math.Cos(holeAngle);
            var sin          = (float)Math.Sin(holeAngle);
            var offset1      = new Vector2(holeDistance * cos, holeDistance * sin);
            var offset2      = new Vector2(-holeDistance * cos, -holeDistance * sin);

            for (int i = 0; i < cnt; i++)
            {
                // Flatten a bit
                var radiusUse = radii[i];
                mPolygonPoints.Add(new Vector2(radii[i] * (Single)Math.Cos(angle), radii[i] * (Single)Math.Sin(angle)));
                hole1.Add(offset1 + new Vector2(innerRadii[i] * (Single)Math.Cos(-angle), innerRadii[i] * (Single)Math.Sin(-angle)));
                hole2.Add(offset2 + new Vector2(innerRadii[i] * (Single)Math.Cos(-angle), innerRadii[i] * (Single)Math.Sin(-angle)));
                angle += angleDiff;
            }

            var holes = new List <List <Vector2> >()
            {
                hole1, hole2
            };

            // Triangulate and measure the Time needed for the Triangulation
            var before = DateTime.Now;
            var sLTI   = SweepLinePolygonTriangulator.Triangulate(mPolygonPoints, holes);
            var after  = DateTime.Now;

            // Generate the Output
            var geometry = new HelixToolkit.Wpf.SharpDX.MeshGeometry3D();

            geometry.Positions = new HelixToolkit.Wpf.SharpDX.Core.Vector3Collection();
            geometry.Normals   = new HelixToolkit.Wpf.SharpDX.Core.Vector3Collection();
            foreach (var point in mPolygonPoints.Union(holes.SelectMany(h => h)))
            {
                geometry.Positions.Add(new Vector3(point.X, 0, point.Y + 5));
                geometry.Normals.Add(new Vector3(0, 1, 0));
            }
            geometry.Indices             = new HelixToolkit.Wpf.SharpDX.Core.IntCollection(sLTI);
            triangulatedPolygon.Geometry = geometry;

            var lb = new LineBuilder();

            for (int i = 0; i < sLTI.Count; i += 3)
            {
                lb.AddLine(geometry.Positions[sLTI[i]], geometry.Positions[sLTI[i + 1]]);
                lb.AddLine(geometry.Positions[sLTI[i + 1]], geometry.Positions[sLTI[i + 2]]);
                lb.AddLine(geometry.Positions[sLTI[i + 2]], geometry.Positions[sLTI[i]]);
            }
            mViewModel.LineGeometry = lb.ToLineGeometry3D();

            // Set the Lines if activated
            if (mViewModel.ShowTriangleLines)
            {
                lineTriangulatedPolygon.Geometry = mViewModel.LineGeometry;
            }
            else
            {
                lineTriangulatedPolygon.Geometry = null;
            }

            // Set the InfoLabel Text
            var timeNeeded = (after - before).TotalMilliseconds;

            infoLabel.Content = String.Format("Last triangulation of {0} Points took {1:0.##} Milliseconds!", triangulatedPolygon.Geometry.Positions.Count, timeNeeded);
        }
Beispiel #5
0
 /// <summary>
 /// Triangulate the polygon by using the sweep line algorithm
 /// </summary>
 /// <returns>An index collection.</returns>
 public Int32Collection Triangulate()
 {
     return(SweepLinePolygonTriangulator.Triangulate(this.points));
 }
Beispiel #6
0
        /// <summary>
        /// Generate a simple Polygon and then triangulate it.
        /// The Result is then Displayed.
        /// </summary>
        /// <param name="sender">The Sender (i.e. the Button)</param>
        /// <param name="e">The routet Event Args</param>
        private void generatePolygonButton_Click(object sender, RoutedEventArgs e)
        {
            // Generate random Polygon
            var random = new Random();
            var cnt    = mViewModel.PointCount;

            mPolygonPoints = new List <Vector2>();
            var angle     = 0f;
            var angleDiff = 2f * (Single)Math.PI / cnt;
            var radius    = 4f;
            // Random Radii for the Polygon
            var radii = new List <float>();

            for (int i = 0; i < cnt; i++)
            {
                radii.Add(radius + random.NextFloat(-radius, radius));
            }
            for (int i = 0; i < cnt; i++)
            {
                var last = i > 0 ? i - 1 : cnt - 1;
                var next = i < cnt - 1 ? i + 1 : 0;
                // Flatten a bit
                var radiusUse = radii[last] * 0.25f + radii[i] * 0.5f + radii[next] * 0.25f;
                mPolygonPoints.Add(new Vector2(radiusUse * (Single)Math.Cos(angle), radiusUse * (Single)Math.Sin(angle)));
                angle += angleDiff;
            }
            // Triangulate and measure the Time needed for the Triangulation
            var before = DateTime.Now;
            var sLTI   = SweepLinePolygonTriangulator.Triangulate(mPolygonPoints);
            var after  = DateTime.Now;

            // Generate the Output
            var geometry = new HelixToolkit.Wpf.SharpDX.MeshGeometry3D();

            geometry.Positions = new HelixToolkit.Wpf.SharpDX.Core.Vector3Collection();
            geometry.Normals   = new HelixToolkit.Wpf.SharpDX.Core.Vector3Collection();
            foreach (var point in mPolygonPoints)
            {
                geometry.Positions.Add(new Vector3(point.X, 0, point.Y + 5));
                geometry.Normals.Add(new Vector3(0, 1, 0));
            }
            geometry.Indices             = new HelixToolkit.Wpf.SharpDX.Core.IntCollection(sLTI);
            triangulatedPolygon.Geometry = geometry;

            var lb = new LineBuilder();

            for (int i = 0; i < sLTI.Count; i += 3)
            {
                lb.AddLine(geometry.Positions[sLTI[i]], geometry.Positions[sLTI[i + 1]]);
                lb.AddLine(geometry.Positions[sLTI[i + 1]], geometry.Positions[sLTI[i + 2]]);
                lb.AddLine(geometry.Positions[sLTI[i + 2]], geometry.Positions[sLTI[i]]);
            }
            mViewModel.LineGeometry = lb.ToLineGeometry3D();

            // Set the Lines if activated
            if (mViewModel.ShowTriangleLines)
            {
                lineTriangulatedPolygon.Geometry = mViewModel.LineGeometry;
            }
            else
            {
                lineTriangulatedPolygon.Geometry = null;
            }

            // Set the InfoLabel Text
            var timeNeeded = (after - before).TotalMilliseconds;

            infoLabel.Content = String.Format("Last triangulation of {0} Points took {1:0.##} Milliseconds!", triangulatedPolygon.Geometry.Positions.Count, timeNeeded);
        }