Exemplo n.º 1
0
        private void BuildTerrain()
        {
            // Figure out where the extra ring of points should go
            double radius = BuildTerrainSprtRadius(_neurons.Select(o => o.Position.ToPoint2D()).ToArray());

            // Figure out how many extra points to make
            int numExtra = BuildTerrainSprtNumExtra(_neurons.Length);

            // Lay down all the points into a single array
            _terrainPoints = UtilityCore.Iterate(
                _neurons.Select(o => o.Position),                                                         // first points are the neuron's locations (don't worry about Z right now, they will change each update)
                Math2D.GetCircle_Cached(numExtra).Select(o => new Point3D(o.X * radius, o.Y * radius, 0)) // tack on a bunch of points around the edge
                ).ToArray();

            // Get the delaunay of these points
            TriangleIndexed[] triangles = Math2D.GetDelaunayTriangulation(_terrainPoints.Select(o => o.ToPoint2D()).ToArray(), _terrainPoints);

            // Convert into linked triangles
            List <TriangleIndexedLinked> trianglesLinked = triangles.Select(o => new TriangleIndexedLinked(o.Index0, o.Index1, o.Index2, o.AllPoints)).ToList();

            TriangleIndexedLinked.LinkTriangles_Edges(trianglesLinked, true);

            _terrainTriangles = trianglesLinked.ToArray();
        }
            private static Point3D[] GetConnectingLinesSprtBetween(TriangleIndexedLinked[] hull, Tuple<int, Point3D> intersect1, Tuple<int, Point3D> intersect2, Tuple<TriangleEdge, Point3D> edgeIntersect1, Tuple<TriangleEdge, Point3D> edgeIntersect2)
            {
                // Start building the return points
                List<Point3D> retVal = new List<Point3D>();

                retVal.Add(intersect1.Item2);
                retVal.Add(edgeIntersect1.Item2);

                // Walk neighbors until intersect2's triangle
                //TODO: To reduce mathmatical drift, go right one triangle from 1, then left one from 2, then right, etc and meet in the middle.  But the
                //drift should be very small, and the polygon clip logic that's done by the caller will transform into/out of 2D anyway.

                //TODO: If the line goes exactly through a corner, this loop could fail

                TriangleIndexedLinked currentTriangle = hull[intersect1.Item1];
                Tuple<TriangleEdge, Point3D> currentIntersect = edgeIntersect1;

                while (true)
                {
                    currentTriangle = currentTriangle.GetNeighbor(currentIntersect.Item1);
                    if (currentTriangle == null)
                    {
                        //TODO: Instead of choking here, go left from 2 as far as possible.  Then just draw a line from the farthest points (jumping
                        //over the hole)
                        throw new ApplicationException("The hull passed in has holes");
                    }

                    if (currentTriangle.Token == hull[intersect2.Item1].Token)
                    {
                        // This is the other side
                        break;
                    }

                    //NOTE: There are some cases where intersect2 will lead backward.  So an extra check is needed to make sure it's going
                    //away from prevTriangle
                    var attemptIntersect = GetPointOnTriangleEdge(currentTriangle, currentIntersect.Item2, intersect2.Item2);       // not using outsideCenterPoint, because that's only some midpoint (between intersect1 and 2).  Since this while loop is marching toward intersect2, then intersect2 is the best outside point to use
                    if (attemptIntersect == null)
                    {
                        #region Reverse guidePoint

                        // This is a copy of what GetPointOnTriangleEdge does
                        Vector3D guideDirection = (intersect2.Item2 - currentIntersect.Item2).GetProjectedVector(currentTriangle);
                        if (Math3D.IsInvalid(guideDirection))
                        {
                            // Guide guideDirection is perpendicular to the triangle
                            throw new ApplicationException("Couldn't find an intersect on the other side of the triangle");
                        }

                        // Now reverse the guide direction
                        attemptIntersect = GetPointOnTriangleEdge(currentTriangle, currentIntersect.Item2, currentIntersect.Item2 - guideDirection);
                        if (attemptIntersect == null)
                        {
                            throw new ApplicationException("Couldn't find an intersect on the other side of the triangle");
                        }

                        #endregion
                    }

                    currentIntersect = attemptIntersect;

                    retVal.Add(currentIntersect.Item2);
                }

                if (!Math3D.IsNearValue(retVal[retVal.Count - 1], edgeIntersect2.Item2))
                {
                    retVal.Add(edgeIntersect2.Item2);       // execution will only get here if hull[intersect1.Item1] is a neighbor to hull[intersect2.Item1] (basically, if the while loop didn't do anything)
                }

                retVal.Add(intersect2.Item2);

                return retVal.ToArray();
            }