예제 #1
0
        //Detects shift used from technique
        public ShiftModes DetectShiftMode()
        {
            ShiftModes shiftm = ShiftModes.None;

            PointF p;

            for (int i = 0; i <= this.GetPointShiftWidth() - 1; i++)
            {
                for (int j = 0; j <= this.GetPointShiftHeight() - 1; j++)
                {
                    p = this.GetPointShift(i, j);

                    if (p.X != 0)
                    {
                        shiftm = shiftm | ShiftModes.Horizontal;
                    }
                    if (p.Y != 0)
                    {
                        shiftm = shiftm | ShiftModes.Vertical;
                    }
                }
            }

            return(shiftm);
        }
예제 #2
0
        //Returns the exact height for a real position (x,y) on the surface
        //Using Surface's technique for information
        public float GetPositionHeight(float x, float y, ShiftModes shiftApplied)
        {
            Vector3[] tri;
            tri = this.GetPositionTriangle(x, y, shiftApplied);           //gets the triangle that the point/ray (x,y) intersects with the surface

            //intersect the plane obtained from the triangle with the ray (x,y) and return the height (z)
            return(Plane.IntersectLine(Plane.FromPoints(tri[0], tri[1], tri[2]), new Vector3(x, y, 0), new Vector3(x, y, 1)).Z);
        }
예제 #3
0
        //Returns the triangle in which a given point (ray) (x,y) is located. It returns the real coordinates of points that form the triangle in which the ray (x,y) goes trough the surface
        //Using Surface's technique for information
        public Vector3[] GetPositionTriangle(float x, float y, ShiftModes shiftApplied)
        {
            ShiftModes shiftm = shiftApplied;

            //detect shifting from technique
            if (shiftApplied == ShiftModes.AutoDetect)
            {
                shiftm = this.SurfaceTechnique.DetectShiftMode();
                if (shiftm == ShiftModes.Both)
                {
                    throw new ExceptionSurface("A horizontal and a vertical shift were both found in this surface's technique. Function GetPositionHeight cannot compute surfaces with a technique that uses shifts both horisontal and vertical! Please use only one kind of shift.");
                }
            }

            //get the tile where the position is located and check if the tile obtained is within surface limits. if not, throw exception
            Point tile = this.GetPositionTile(x, y, shiftApplied);

            if (!Misc.WithinBounds(tile, this.Size, -2, -2))
            {
                throw new ExceptionSurface("The tile that contains the point (" + x + "," + y + ") is not within surface limits!");                                                       //okay, uses offsets of -2 because: for once the tile number is one less than the points in a surface, which is returned in this.size. and another thing is that the function verifies in interval [0,size] but it must not include size in our case, because from 0 to size-1 is the boundary that includes all good points
            }
            HatchingMode tileHatch = this.GetTileHatching(tile.X, tile.Y);

            //determine the triangle from this tile that contains this point
            //same algorithm for any shift mode works
            Vector3 p1, p2;            //points that determin the hatching line on this tile
            Vector3 A, B, C;           //points of the triangle that contains this point

            if (tileHatch == HatchingMode.NWSE)
            {
                p1 = this.GetPointRealCoordinatesXYHeight(tile.X, tile.Y + 1, true);
                p2 = this.GetPointRealCoordinatesXYHeight(tile.X + 1, tile.Y, true);

                PointF pInter = Line2D.Intersection(Line2D.FromTwoPoints(p1.X, p1.Y, p2.X, p2.Y), new Line2D(x, y, 0, 1)); //determine the intersection point between a vertical line that goes through the point and the one that determines the hatching. The result can help determine which triangle exacly this point belongs to

                bool leftTriangle = true;                                                                                  // consider it is the left triangle first, for faster computing

                //lines were parallel and the point is on the right triangle
                if (float.IsInfinity(pInter.Y))
                {
                    if (x > p1.X)
                    {
                        leftTriangle = false;
                    }
                }

                //lines not parallel, but the point is on the right triangle
                if (y > pInter.Y)
                {
                    leftTriangle = false;
                }

                //set the triangle (obs: one point was not calculated)
                if (leftTriangle)
                {
                    A = p1;
                    B = p2;
                    C = this.GetPointRealCoordinatesXYHeight(tile.X, tile.Y, true);
                }
                else                 //right triangle
                {
                    A = p1;
                    B = this.GetPointRealCoordinatesXYHeight(tile.X + 1, tile.Y + 1, true);
                    C = p2;
                }
            }
            else             //NESW
            {
                p1 = this.GetPointRealCoordinatesXYHeight(tile.X, tile.Y, true);
                p2 = this.GetPointRealCoordinatesXYHeight(tile.X + 1, tile.Y + 1, true);

                PointF pInter = Line2D.Intersection(Line2D.FromTwoPoints(p1.X, p1.Y, p2.X, p2.Y), new Line2D(x, y, 0, 1)); //determine the intersection point between a vertical line that goes through the point and the one that determines the hatching. The result can help determine which triangle exacly this point belongs to

                bool leftTriangle = true;                                                                                  // consider it is the left triangle first, for faster computing

                //lines were parallel and the point is on the right triangle
                if (float.IsInfinity(pInter.Y))
                {
                    if (x > p1.X)
                    {
                        leftTriangle = false;
                    }
                }

                //lines not parallel, but the point is on the right triangle
                if (y < pInter.Y)
                {
                    leftTriangle = false;
                }

                //set the triangle (obs: one point was not calculated)
                if (leftTriangle)
                {
                    A = p1;
                    B = this.GetPointRealCoordinatesXYHeight(tile.X, tile.Y + 1, true);
                    C = p2;
                }
                else                 //right triangle
                {
                    A = p1;
                    B = p2;
                    C = this.GetPointRealCoordinatesXYHeight(tile.X + 1, tile.Y, true);
                }
            }

            //returns the triangle in the form of an 3 elements array of Vector3 object. (The triangle is given clockwise, relative to the surface)
            Vector3[] triangle = new Vector3[3];
            triangle[0] = A; triangle[1] = B; triangle[2] = C;

            return(triangle);
        }
예제 #4
0
        //Returns the tile point that contains a certain position (x,y) on the surface
        //Using Surface's technique for information
        public Point GetPositionTile(float x, float y, ShiftModes shiftApplied)
        {
            Point tile = new Point(0, 0);            //holds the result

            ShiftModes shiftm = shiftApplied;

            //detect shifting from technique
            if (shiftApplied == ShiftModes.AutoDetect)
            {
                shiftm = this.SurfaceTechnique.DetectShiftMode();
                if (shiftm == ShiftModes.Both)
                {
                    throw new ExceptionSurface("A horizontal and a vertical shift were both found in this surface's technique. Function GetPositionHeight cannot compute surfaces with a technique that uses shifts both horisontal and vertical! Please use only one kind of shift.");
                }
            }


            //different algortitms for different shift modes, although somehow analogues
            if (shiftm == ShiftModes.None)
            {
                //NO SHIFT mode (fast computing)

                tile.X = (int)Math.Floor(x / this.SurfaceTechnique.TileSize.Width);               //the column this point is in
                tile.Y = (int)Math.Floor(y / this.SurfaceTechnique.TileSize.Height);              //the row this point is in
            }
            else if (shiftm == ShiftModes.Horizontal)
            {
                //HORIZONTAL SHIFT mode

                tile.Y = (int)Math.Floor(y / this.SurfaceTechnique.TileSize.Height);               //the row this point is in

                //lower/upper points line (projection on lower/upper points line of this tile line):
                int tileXLower, tileXUpper;                //column of the tile in which the lower/upper projection of the point is located
                tileXLower = this.GetTileForProjectedX(tile.Y, x);
                tileXUpper = this.GetTileForProjectedX(tile.Y + 1, x);

                if (tileXLower == tileXUpper)                 //it is clearly in this tile
                {
                    tile.X = tileXLower;
                }
                else                                                                                               //could be in either of these two or between them
                {
                    Vector2 pLower, pUpper;                                                                        //keep the positions of each couple of points that separate each two tiles in which the point might be
                    bool    found = false;                                                                         //changes to true when the tile is found

                    for (int i = Math.Min(tileXLower, tileXUpper) + 1; i <= Math.Max(tileXLower, tileXUpper); i++) //verify (agains the point) each line in between two consecutive tiles from the lowest possible tile to the highest one to see where the point is
                    {
                        pLower = this.GetPointRealCoordinatesXY(i, tile.Y, true);
                        pUpper = this.GetPointRealCoordinatesXY(i, tile.Y + 1, true);

                        PointF pInter = Line2D.Intersection(Line2D.FromTwoPoints(pUpper.X, pUpper.Y, pLower.X, pLower.Y), new Line2D(x, y, 0, 1));                      //gets the intersection between the determination line (the line between these two tiles) and the projection line of the point on OX

                        //the two cases when the point is to the left of the determination line (the line that separates the two tiles) which means the point belongs to the left tile -> i-1;
                        if (pUpper.X > pLower.X)
                        {
                            if (y > pInter.Y)
                            {
                                tile.X = i - 1;
                                found  = true;
                                break;
                            }
                        }
                        if (pUpper.X < pLower.X)
                        {
                            if (y < pInter.Y)
                            {
                                tile.X = i - 1;
                                found  = true;
                                break;
                            }
                        }
                    }

                    if (!found)
                    {
                        tile.X = Math.Max(tileXLower, tileXUpper);                            //is no tile is found in the left of each line that separates two lines (the determination lines) then the point is surely in the mostright tile from the series of tiles found
                    }
                }
            }
            else if (shiftm == ShiftModes.Vertical)
            {
                //VERTICAL SHIFT mode

                // !!! NEEDS DONE FOR VERTICAL SHIFT AS WELL !!!
            }

            return(tile);
        }