Esempio n. 1
0
        public static double Cotangent(TriVertex thePoint, TriVertex basePt1, TriVertex basePt2)
        {
            double Eps          = 0.000001;
            double crossProduct = XProduct(thePoint, basePt1, basePt2);

            return(Math.Abs(crossProduct) < Eps ? noCotangent : DotProduct(thePoint, basePt1, basePt2) / crossProduct);
        }
Esempio n. 2
0
        /// <summary>
        /// { Returns the triangle neighbouring aTriangle which is nearer to
        /// aPoint than aTriangle.If aPoint is in aTriangle then aTriangle is
        /// returned, and found set to true. If aPoint is outside the model,
        /// returns Nil - requires model to be convex. }
        /// </summary>
        /// <param name="aPoint"></param>
        /// <param name="aTriangle"></param>
        /// <param name="lastTri"></param>
        /// <param name="found"></param>
        /// <returns></returns>
        protected Triangle GetBestTri(TriVertex aPoint, Triangle aTriangle, Triangle lastTri, out bool found)
        {
            Triangle Result;

            found = false;

            TriVertex firstPoint  = aTriangle.Vertices[0];
            TriVertex secondPoint = aTriangle.Vertices[1];

            if (aTriangle.Neighbours[0] != lastTri && TinningUtils.DefinitelyLeftOfBaseLine(aPoint, firstPoint, secondPoint))
            {
                Result = aTriangle.Neighbours[0];
            }
            else
            {
                TriVertex thirdPoint = aTriangle.Vertices[2];
                if (aTriangle.Neighbours[1] != lastTri && TinningUtils.DefinitelyLeftOfBaseLine(aPoint, secondPoint, thirdPoint))
                {
                    Result = aTriangle.Neighbours[1];
                }
                else if (aTriangle.Neighbours[2] != lastTri && TinningUtils.DefinitelyLeftOfBaseLine(aPoint, thirdPoint, firstPoint))
                {
                    Result = aTriangle.Neighbours[2];
                }
                else // to the right of each line -must be inside aTriangle
                {
                    Result = aTriangle;
                    found  = true;
                }
            }

            return(Result);
        }
Esempio n. 3
0
        public void Creation_FromCoordinates()
        {
            var vertex = new TriVertex(1, 2, 3);

            vertex.X = 1;
            vertex.Y = 2;
            vertex.Z = 3;
        }
Esempio n. 4
0
        public void IsEqual_WithTolerance()
        {
            var vertex1 = new TriVertex(1, 2, 3);
            var vertex2 = new TriVertex(1.1, 2.1, 3.1);

            vertex1.IsEqual(1, 2, 3, 0.0001).Should().BeTrue();
            vertex2.IsEqual(1, 2, 3, 0.0001).Should().BeFalse();
            vertex2.IsEqual(1, 2, 3, 0.2).Should().BeTrue();
        }
Esempio n. 5
0
        public void IsEqual_Vertex()
        {
            var vertex1 = new TriVertex(1, 2, 3);
            var vertex2 = new TriVertex(1, 2, 3);
            var vertex3 = new TriVertex(2, 3, 4);

            vertex1.IsEqual(vertex2, 0.001).Should().BeTrue();
            vertex1.IsEqual(vertex3, 0.001).Should().BeFalse();
        }
Esempio n. 6
0
        public void Creation_FromXYZ()
        {
            var vertex  = new TriVertex(1, 2, 3);
            var vertex2 = new TriVertex(vertex.XYZ);

            vertex2.X = 1;
            vertex2.Y = 2;
            vertex2.Z = 3;
        }
Esempio n. 7
0
        /// <summary>
        /// Add four coords to the model, which form the minimum bounding rectangle
        /// about the selected points.Return these.
        /// </summary>
        /// <param name="tl"></param>
        /// <param name="tr"></param>
        /// <param name="bl"></param>
        /// <param name="br"></param>
        protected void MakeMinimumBoundingRectangle(out TriVertex tl, out TriVertex tr, out TriVertex bl, out TriVertex br)
        {
            const int aBit = 10; // Arbitrary size expansion for encompassing rectangle

            tl = AddVertex(TIN.Header.MinimumEasting - aBit, TIN.Header.MaximumNorthing + aBit, 0);
            tr = AddVertex(TIN.Header.MaximumEasting + aBit, TIN.Header.MaximumNorthing + aBit, 0);
            bl = AddVertex(TIN.Header.MinimumEasting - aBit, TIN.Header.MinimumNorthing - aBit, 0);
            br = AddVertex(TIN.Header.MaximumEasting + aBit, TIN.Header.MinimumNorthing - aBit, 0);
        }
Esempio n. 8
0
        public void Test_Triangle_ToString()
        {
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v1, v2, v3);

            tri.ToString().Should().ContainAll(new[] { "Vertices:", "Neighbours:" });
        }
Esempio n. 9
0
        public void Creation_SetFomXYZ()
        {
            var vertex  = new TriVertex(0, 0, 0);
            var vertex2 = new TriVertex(vertex.XYZ);

            vertex.XYZ = vertex2.XYZ;

            vertex2.X = 1;
            vertex2.Y = 2;
            vertex2.Z = 3;
        }
Esempio n. 10
0
        public Triangle AddTriangle(TriVertex V1, TriVertex V2, TriVertex V3)
        {
            // Add the triangle and assign its tag member to be its position in the list (ie: it will be the last one)
            Triangle tri = TIN.Triangles.AddTriangle(V1, V2, V3);

            tri.Tag = TIN.Triangles.Count;

            TriangleAdded(tri);

            return(tri);
        }
Esempio n. 11
0
        public void Triangle_Area()
        {
            // Three clock wise coordinates
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v1, v2, v3);

            tri.Area().Should().Be(0.5);
        }
Esempio n. 12
0
        /// <summary>
        /// Add the two starting triangles.
        /// </summary>
        /// <param name="tl"></param>
        /// <param name="tr"></param>
        /// <param name="bl"></param>
        /// <param name="br"></param>
        protected void CreateInitialTriangles(TriVertex tl, TriVertex tr, TriVertex bl, TriVertex br)
        {
            AddTriangle(tl, tr, bl);
            AddTriangle(bl, tr, br);

            // Ensure their neighbours are correct
            TIN.Triangles[0].Neighbours[1] = TIN.Triangles[1];
            TIN.Triangles[1].Neighbours[0] = TIN.Triangles[0];

            TIN.Triangles.NumberTriangles();
        }
Esempio n. 13
0
        public void Triangle_Centroid()
        {
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v1, v2, v3);

            tri.Centroid().Should().BeEquivalentTo(new XYZ((v1.X + v2.X + v3.X) / 3,
                                                           (v1.Y + v2.Y + v3.Y) / 3,
                                                           (v1.Z + v2.Z + v3.Z) / 3));
        }
Esempio n. 14
0
 protected void UpdateNeighbour(Triangle theTri, TriVertex thePoint, Triangle newTri)
 {
     if (theTri != null)
     {
         for (int j = 0; j < 3; j++)
         {
             if (theTri.Vertices[j] == thePoint)
             {
                 theTri.Neighbours[XYZ.PrevSide(j)] = newTri;
             }
         }
     }
 }
Esempio n. 15
0
        public void Triangle_GetSideIndex_AntiClockwise()
        {
            // Three clock wise coordinates
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v3, v2, v1);

            tri.GetSideIndex(v1, v2).Should().Be(1);
            tri.GetSideIndex(v2, v3).Should().Be(0);
            tri.GetSideIndex(v3, v1).Should().Be(2);
        }
Esempio n. 16
0
        public void Triangle_PointInTriangleInclusive()
        {
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v1, v2, v3);

            tri.PointInTriangleInclusive(0.5, 0.5).Should().Be(XYZ.PointInTriangleInclusive(v1.XYZ, v2.XYZ, v3.XYZ, 0.5, 0.5));
            tri.PointInTriangleInclusive(0, 0).Should().Be(XYZ.PointInTriangleInclusive(v1.XYZ, v2.XYZ, v3.XYZ, 0, 0));
            tri.PointInTriangleInclusive(0, 1.0).Should().Be(XYZ.PointInTriangleInclusive(v1.XYZ, v2.XYZ, v3.XYZ, 0, 1.0));
            tri.PointInTriangleInclusive(1.0, 0).Should().Be(XYZ.PointInTriangleInclusive(v1.XYZ, v2.XYZ, v3.XYZ, 1.0, 0));
        }
Esempio n. 17
0
        public void Triangle_Clockwise()
        {
            // Three clock wise coordinates
            var v1 = new TriVertex(0, 0, 0);
            var v2 = new TriVertex(0, 1, 0);
            var v3 = new TriVertex(1, 1, 0);

            var tri = new Triangle(v1, v2, v3);

            tri.IsClockwise().Should().BeTrue();

            var tri2 = new Triangle(v3, v2, v1);

            tri2.IsClockwise().Should().BeFalse();
        }
Esempio n. 18
0
        public void TinningEngineTetss_AddTriangle()
        {
            TinningEngine engine = new TinningEngine();

            engine.TIN.Vertices.InitPointSearch(-10, -10, 10, 10, 10);

            TriVertex v0 = engine.AddVertex(0, 0, 0);
            TriVertex v1 = engine.AddVertex(1, 0, 0);
            TriVertex v2 = engine.AddVertex(0, 1, 0);

            Triangle t = engine.AddTriangle(v0, v1, v2);

            Assert.True(engine.TIN.Triangles.Count == 1);
            Assert.True(engine.TIN.Triangles[0] == t);
        }
Esempio n. 19
0
        public void TinningEngineTetss_AddVertex()
        {
            TinningEngine engine = new TinningEngine();

            engine.TIN.Vertices.InitPointSearch(-10, -10, 10, 10, 10);

            TriVertex v = engine.AddVertex(1, 2, 3);

            Assert.True(v.X == 1);
            Assert.True(v.Y == 2);
            Assert.True(v.Z == 3);

            Assert.True(engine.TIN.Vertices.Count == 1);
            Assert.True(engine.TIN.Vertices[0] == v);
        }
Esempio n. 20
0
        /* Re-include if required, and add unit tests for them at that time.
         * /// <summary>
         * /// Ensure lastTri is not discarded (ie invalid). If so, return a valid triangle
         * /// </summary>
         * /// <param name="lastTri"></param>
         * protected void CheckLastTri(ref Triangle lastTri)
         * {
         * if (lastTri == null)
         *  lastTri = TIN.Triangles[0];
         *
         * if (lastTri.IsDiscardedFlag)
         *  for (int i = 0; i < TIN.Triangles.Count; i++)
         *    if (!TIN.Triangles[i].IsDiscardedFlag)
         *    {
         *      lastTri = TIN.Triangles[i];
         *      return;
         *    }
         *
         * if (lastTri.IsDiscardedFlag)
         *  lastTri = null;
         * }
         */

        /// <summary>
        /// NOTE - if aPoint is possibly a point currently in the model, it is
        /// faster and safer to use getTriangle().  Do not assume that
        /// locateTriangle() will actually find the triangle that an existing
        /// point is a vertex of, due to floating point inaccuracies
        /// </summary>
        /// <param name="coord"></param>
        /// <param name="lastTri"></param>
        /// <param name="checkIt"></param>
        /// <returns></returns>
        protected Triangle LocateTriangle2(TriVertex coord, Triangle lastTri, bool checkIt)
        {
            int  nSteps       = 0;
            bool found        = false;
            bool outsideModel = false;

            if (lastTri == null)
            {
                lastTri = TIN.Triangles[0];
            }

            /* Re-include if required, and add unit tests for them at that time.
             * if (checkIt)
             * CheckLastTri(ref lastTri);
             */

            if (lastTri == null) // No undiscarded triangles left
            {
                return(null);
            }

            int      StartAt    = 0;
            Triangle currentTri = lastTri;

            while (!outsideModel && !found)
            {
                if (++nSteps > MaxTriangleLocationSteps)
                {
                    surfaceWalkOverflowCount++;
                    nSteps = 0;

                    // Try again from another start triangle
                    StartAt    = (StartAt + 7919) % TIN.Triangles.Count; // 7919 is an appropriate sized prime
                    lastTri    = TIN.Triangles[StartAt];
                    currentTri = lastTri;
                }

                Triangle nextTri = GetBestTri(coord, currentTri, lastTri, out found);
                lastTri      = currentTri;
                currentTri   = nextTri;
                outsideModel = currentTri == null;
            }

            return(found ? currentTri : null);
        }
Esempio n. 21
0
        protected Triangle NewTriangle(TriVertex coord1, TriVertex coord2, TriVertex coord3, Triangle side1, Triangle side2, Triangle side3)
        {
            Triangle result;

            if (succLastTriangle != null)
            {
                result = succLastTriangle;

                if (coord1.X == coord2.X && coord1.Y == coord2.Y ||
                    coord2.X == coord3.X && coord2.Y == coord3.Y ||
                    coord3.X == coord1.X && coord3.Y == coord1.Y)
                {
                    // TIN.SaveToFile($@"C:\Temp\TINStateBeforeCoordNonUniquenessException({DateTime.Now.Ticks}).ttm", false);

                    throw new TRexTINException($"Coordinates for new triangle are not unique {string.Concat(new object[] {coord1, coord2, coord3})}");
                }

                result.Vertices[0] = coord1;
                result.Vertices[1] = coord2;
                result.Vertices[2] = coord3;

                TIN.Triangles.Add(result);

                TriangleAdded(result);
            }
            else
            {
                result = TIN.Triangles.AddTriangle(coord1, coord2, coord3);

                TriangleAdded(result);
            }

            if (result == side1 || result == side2 || result == side3)
            {
                throw new TRexTINException($"Triangle cannot be its own neighbour: Tri={result}, versus neighbours={string.Concat(new object[] {side1, side2, side3})}");
            }

            result.Neighbours[0] = side1;
            result.Neighbours[1] = side2;
            result.Neighbours[2] = side3;

            return(result);
        }
Esempio n. 22
0
        /// <summary>
        /// IncorporateCoord adds a vertex into the TIN by locating the triangle
        /// the coordinate lies in then adding the vertex to the model
        /// </summary>
        /// <param name="theCoord"></param>
        /// <param name="currentTri"></param>
        /// <returns></returns>
        protected bool IncorporateCoord(TriVertex theCoord, ref Triangle currentTri)
        {
            bool result = false;

            currentTri = LocateTriangle2(theCoord, currentTri, false);
            if (currentTri != null)
            {
                AddCoordToModel(theCoord, currentTri);

                if (succLastTriangle != null)
                {
                    throw new TRexTINException("Not all created triangles used.");
                }

                result = true;
            }

            return(result);
        }
Esempio n. 23
0
        private void InitialiseTriangleVertexOrdering()
        {
            v0 = ScanTri.Vertices[0];
            v1 = ScanTri.Vertices[1];
            v2 = ScanTri.Vertices[2];

            // Sort the three vertices in ascending Y order. The three compares and swaps
            // are more efficient than calling qsort to do it.
            if (v0.Y > v1.Y)
            {
                MinMax.Swap(ref v0, ref v1);
            }
            if (v1.Y > v2.Y)
            {
                MinMax.Swap(ref v1, ref v2);
            }
            if (v0.Y > v1.Y)
            {
                MinMax.Swap(ref v0, ref v1);
            }
        }
Esempio n. 24
0
        /// <summary>
        /// Returns true if the circumcircle of theTri contains theCoordRec
        /// </summary>
        /// <param name="theTri"></param>
        /// <param name="theCoord"></param>
        /// <returns></returns>
        protected bool Influenced(Triangle theTri, TriVertex theCoord)
        {
            var result = false;

            double cotan = TinningUtils.Cotangent(theTri.Vertices[2], theTri.Vertices[0], theTri.Vertices[1]);

            if (cotan > -1E20)
            {
                double cNorth = ((theTri.Vertices[1].Y + theTri.Vertices[0].Y) / 2) -
                                ((theTri.Vertices[1].X - theTri.Vertices[0].X) / 2) *
                                cotan;
                double cEast = ((theTri.Vertices[1].X + theTri.Vertices[0].X) / 2) +
                               ((theTri.Vertices[1].Y - theTri.Vertices[0].Y) / 2) *
                               cotan;
                double radSq = Math.Pow(cNorth - theTri.Vertices[0].Y, 2) + Math.Pow(cEast - theTri.Vertices[0].X, 2);

                result = Math.Pow(theCoord.X - cEast, 2) + Math.Pow(theCoord.Y - cNorth, 2) < radSq;
            }

            return(result);
        }
Esempio n. 25
0
        protected void makeUpdatedTriangle(Triangle tri,
                                           TriVertex firstCoord,
                                           TriVertex secondCoord,
                                           TriVertex thirdCoord,
                                           Triangle firstSide,
                                           Triangle secondSide,
                                           Triangle thirdSide)
        {
            if (tri == firstSide || tri == secondSide || tri == thirdSide)
            {
                throw new TRexTINException($"Triangle cannot be its own neighbour: Tri={tri}, versus neighbours={string.Concat(new object[] {firstSide, secondSide, thirdSide})}");
            }

            tri.Vertices[0]   = firstCoord;
            tri.Vertices[1]   = secondCoord;
            tri.Vertices[2]   = thirdCoord;
            tri.Neighbours[0] = firstSide;
            tri.Neighbours[1] = secondSide;
            tri.Neighbours[2] = thirdSide;

            TriangleUpdated(tri);
        }
Esempio n. 26
0
        /// <summary>
        /// IncorporateCoordIntoTriangle adds a vertex into the given triangle
        /// already existing in the model
        /// </summary>
        /// <param name="theCoord"></param>
        /// <param name="tri"></param>
        public void IncorporateCoordIntoTriangle(TriVertex theCoord, Triangle tri)
        {
            // Noisy logging - reinclude as necessary
            //Log.LogDebug($"Incorporating vertex {theCoord} into triangle {tri}");

            /* Handy debug code...
             * // If the coord being added is equivalent to any of the vertices of the trianlge being added into then there is nothing more to do here
             * if (theCoord.X == tri.Vertices[0].X && theCoord.Y == tri.Vertices[0].Y ||
             *  theCoord.X == tri.Vertices[1].X && theCoord.Y == tri.Vertices[1].Y ||
             *  theCoord.X == tri.Vertices[2].X && theCoord.Y == tri.Vertices[2].Y)
             * {
             * TIN.SaveToFile($@"C:\Temp\TINStateIncorporateCoordIntoTriangleExitWithMatchingVertex({DateTime.Now.Ticks}).ttm", false);
             * return;
             * }
             */

            AddCoordToModel(theCoord, tri);

            if (succLastTriangle != null)
            {
                throw new TRexTINException("Not all created triangles used.");
            }
        }
Esempio n. 27
0
        public void AdjustLimits()
        {
            var vertex1 = new TriVertex(1, 2, 3);
            var vertex2 = new TriVertex(1.1, 2.1, 3.1);
            var vertex3 = new TriVertex(0.9, 1.9, 2.9);

            double minX = double.MaxValue, minY = double.MaxValue, minZ = double.MaxValue;
            double maxX = double.MinValue, maxY = double.MinValue, maxZ = double.MinValue;

            vertex1.AdjustLimits(ref minX, ref minY, ref minZ, ref maxX, ref maxY, ref maxZ);

            minX.Should().Be(1);
            minY.Should().Be(2);
            minZ.Should().Be(3);
            maxX.Should().Be(1);
            maxY.Should().Be(2);
            maxZ.Should().Be(3);

            vertex2.AdjustLimits(ref minX, ref minY, ref minZ, ref maxX, ref maxY, ref maxZ);

            minX.Should().Be(1);
            minY.Should().Be(2);
            minZ.Should().Be(3);
            maxX.Should().Be(1.1);
            maxY.Should().Be(2.1);
            maxZ.Should().Be(3.1);

            vertex3.AdjustLimits(ref minX, ref minY, ref minZ, ref maxX, ref maxY, ref maxZ);

            minX.Should().Be(0.9);
            minY.Should().Be(1.9);
            minZ.Should().Be(2.9);
            maxX.Should().Be(1.1);
            maxY.Should().Be(2.1);
            maxZ.Should().Be(3.1);
        }
Esempio n. 28
0
        public static void GradientFill(Graphics graphics, Rectangle target,
                                        Color startColor, Color endColor,
                                        GradientDirection direction)
        {
            if (!GradientFillSupported)
            {
                return;
            }

            var hdc = graphics.GetHdc();

            try
            {
                var vertices = new TriVertex[]
                {
                    new TriVertex(target.Left, target.Top, startColor),
                    new TriVertex(target.Right, target.Bottom, endColor)
                };
                var rectangles = new GradientRect[]
                {
                    new GradientRect()
                    {
                        UpperLeft  = 0,
                        LowerRight = 1
                    }
                };

                GradientFill(hdc, vertices, 2, rectangles, 1,
                             direction == GradientDirection.Horizontal ?
                             GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V);
            }
            finally
            {
                graphics.ReleaseHdc(hdc);
            }
        }
Esempio n. 29
0
 public GridToTINTriangle(TriVertex Vertex1, TriVertex Vertex2, TriVertex Vertex3) : base(Vertex1, Vertex2, Vertex3)
 {
 }
Esempio n. 30
0
        private void Create(IRenderLayer layer)
        {
            var zoom   = Context.Zoom;
            var colors = layer.Colors.Data;

            int length = colors.Length;

            int size = layer.Points.Size;
            var data = layer.Points.Data;

            if (length != data.Length / size)
            {
                throw new Exception();
            }

            this.points = new TriVertex[length];

            TriVertex vertex;
            Color     color;
            PointF    p = new PointF((float)data[0], (float)data[1]);

            zoom.WorldToScreen(ref p);

            // Get correction distance
            float dx = (p.X - (int)p.X) * 2.0f;
            float dy = (p.Y - (int)p.Y) * 2.0f;

            // Create vertices.
            for (int i = 0; i < length; i++)
            {
                p.X = (float)data[size * i];
                p.Y = (float)data[size * i + 1];

                zoom.WorldToScreen(ref p);

                color = colors[i];

                vertex = new TriVertex();

                vertex.x = (int)(p.X + dx);
                vertex.y = (int)(p.Y + dy);

                vertex.Red   = (ushort)(color.R << 8);
                vertex.Green = (ushort)(color.G << 8);
                vertex.Blue  = (ushort)(color.B << 8);
                vertex.Alpha = (ushort)(color.A << 8);

                this.points[i] = vertex;
            }

            var triangles = layer.Indices.Data;

            length = triangles.Length / 3;

            this.elements = new GradientTriangle[length];

            GradientTriangle e;

            // Create triangles.
            for (int i = 0; i < length; i++)
            {
                e = new GradientTriangle();

                e.Vertex1 = (uint)triangles[3 * i];
                e.Vertex2 = (uint)triangles[3 * i + 1];
                e.Vertex3 = (uint)triangles[3 * i + 2];

                this.elements[i] = e;
            }
        }
Esempio n. 31
0
 /// <summary>
 /// The GradientFill function fills rectangle and triangle structures
 /// </summary>
 /// <param name="hdc">Handle to the destination device contex</param>
 /// <param name="pVertex">Array of TRIVERTEX structures that each define a triangle vertex</param>
 /// <param name="nVertex">The number of vertices in pVertex</param>
 /// <param name="pMesh">an array of GRADIENT_RECT structures in rectangle mode</param>
 /// <param name="nMesh">The number of elements in pMesh</param>
 /// <param name="ulMode">Specifies gradient fill mode</param>
 /// <returns>If the function succeeds, the return value is true, false</returns>
 public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientRect[] pMesh,
     uint nMesh, GradientFillMode ulMode)
 {
     return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
 }