Example #1
0
 public static void HexEdges(PathUtil.PathType type, out float[] edgeX, out float[] edgeY)
 {
     edgeX = (type == PathUtil.PathType.Hex) ? RenderUtil.HexEdgesX : RenderUtil.SquareEdgesX;
     edgeY = (type == PathUtil.PathType.Hex) ? RenderUtil.HexEdgesY : RenderUtil.SquareEdgesY;
 }
Example #2
0
        public BorderPath(Border border, Sector sector, PathUtil.PathType type)
        {
            float[] edgeX, edgeY;
            RenderUtil.HexEdges(type, out edgeX, out edgeY);

            int lengthEstimate = border.Path.Count() * 3;
            List<PointF> borderPathPoints = new List<PointF>(lengthEstimate);
            List<byte> borderPathTypes = new List<byte>(lengthEstimate);
            List<PointF> clipPathPoints = new List<PointF>(lengthEstimate);
            List<byte> clipPathTypes = new List<byte>(lengthEstimate);
            List<List<PointF>> curves = new List<List<PointF>>(lengthEstimate);
            List<PointF> curve = new List<PointF>(lengthEstimate);

            // Based on http://dotclue.org/t20/sec2pdf - J Greely rocks my world.

            int checkFirst = 0;
            int checkLast = 5;

            Hex startHex = Hex.Empty;
            bool startHexVisited = false;

            foreach (Hex hex in border.Path)
            {
                checkLast = checkFirst + 5;

                if (startHexVisited && hex == startHex)
                {
                    // I'm in the starting hex, and I've been
                    // there before, so stop testing at neighbor
                    // 5, no matter what
                    checkLast = 5;

                    // degenerate case, entering for third time
                    if (checkFirst < 3)
                        break;
                }
                else if (!startHexVisited)
                {
                    startHex = hex;
                    startHexVisited = true;

                    // PERF: This seems costly... analyze it!
                    PointF newPoint = Astrometrics.HexToCenter(Astrometrics.LocationToCoordinates(new Location(sector.Location, hex)));
                    newPoint.X += edgeX[0];
                    newPoint.Y += edgeY[0];

                    // MOVETO
                    borderPathPoints.Add(newPoint);
                    borderPathTypes.Add((byte)PathPointType.Start);

                    // MOVETO
                    clipPathPoints.Add(newPoint);
                    clipPathTypes.Add((byte)PathPointType.Start);

                    if (curve.Count > 1)
                    {
                        curves.Add(curve);
                        curve = new List<PointF>(lengthEstimate);
                        curve.Add(newPoint);
                    }
                    else
                    {
                        curve.Clear();
                        curve.Add(newPoint);
                    }
                }

                PointF pt = Astrometrics.HexToCenter(Astrometrics.LocationToCoordinates(new Location(sector.Location, hex)));

                int i = checkFirst;
                for (int check = checkFirst; check <= checkLast; check++)
                {
                    i = check;
                    Hex neighbor = Astrometrics.HexNeighbor(hex, i % 6);

                    if (border.Path.Contains(neighbor)) // TODO: Consider a hash here
                        break;

                    PointF newPoint = new PointF(pt.X + edgeX[(i + 1) % 6], pt.Y + edgeY[(i + 1) % 6]);

                    // TODO: Replace this by clipping borders to sector bounds; problem - bottom/right edges protrude
                    // Only actually render edges within the sector
                    //if( 1 <= ( hex / 100 ) && ( hex / 100 ) <= 32 && 1 <= ( hex % 100 ) && ( hex % 100 ) <= 40 )
                    {
                        // LINETO
                        borderPathPoints.Add(newPoint);
                        borderPathTypes.Add((byte)PathPointType.Line);

                        //curve.Add( newPoint );

                        if (hex.IsValid)
                        {
                            curve.Add(newPoint);
                        }
                        else
                        {
                            if (curve.Count > 1)
                            {
                                curves.Add(curve);
                                curve = new List<PointF>(lengthEstimate);
                                curve.Add(newPoint);
                            }
                            else
                            {
                                curve.Clear();
                                curve.Add(newPoint);
                            }
                        }

                    }
                    /*
                    else
                    {
                        // MOVETO
                        if( borderPathTypes[ borderPathTypes.Count - 1 ] == (byte)PathPointType.Start )
                        {
                            // Collapse multiple MOVETOs - makes GDI+ happy
                            borderPathPoints[ borderPathPoints.Count - 1 ] = newPoint;
                        }
                        else
                        {
                            borderPathPoints.Add( newPoint );
                            borderPathTypes.Add( (byte)PathPointType.Start );
                        }

                        if( curve.Count > 1 )
                        {
                            curves.Add( curve );
                            curve = new List<PointF>( lengthEstimate );
                            curve.Add( newPoint );
                        }
                        else
                        {
                            curve.Clear();
                            curve.Add( newPoint );
                        }
                    }
                     * */
                    // LINETO
                    clipPathPoints.Add(newPoint);
                    clipPathTypes.Add((byte)PathPointType.Line);
                }
                i = i % 6;
                // i is the direction to the next border hex,
                // and when we get there, we'll have come from
                // i + 3, so we start checking with i + 4.
                checkFirst = (i + 4) % 6;
            }

            // Trim trailing MOVETOs - makes GDI+ happy
            while (borderPathTypes.Count > 0 && borderPathTypes[borderPathTypes.Count - 1] == (byte)PathPointType.Start)
            {
                borderPathTypes.RemoveAt(borderPathTypes.Count - 1);
                borderPathPoints.RemoveAt(borderPathPoints.Count - 1);
            }

            borderPathTypes[borderPathTypes.Count - 1] |= (byte)PathPointType.CloseSubpath;

            this.borderPathPoints = borderPathPoints.ToArray();
            this.borderPathTypes = borderPathTypes.ToArray();
            this.clipPathPoints = clipPathPoints.ToArray();
            this.clipPathTypes = clipPathTypes.ToArray();

            if (curve.Count > 1)
                curves.Add(curve);

            curvePoints = curves.Select(c => c.ToArray()).ToArray();
        }
Example #3
0
        internal ClipPath ComputeClipPath(PathUtil.PathType type)
        {
            lock (this)
            {
                if (clipPathsCache[(int)type] == null)
                    clipPathsCache[(int)type] = new ClipPath(this, type);
            }

            return clipPathsCache[(int)type];
        }
Example #4
0
        internal BorderPath ComputeGraphicsPath(Sector sector, PathUtil.PathType type)
        {
            lock (this)
            {
                if (borderPathsCache[(int)type] == null)
                    borderPathsCache[(int)type] = new BorderPath(this, sector, type);
            }

            return borderPathsCache[(int)type];
        }
Example #5
0
            public ClipPath(Sector sector, PathUtil.PathType borderPathType)
            {
                float[] edgex, edgey;
                RenderUtil.HexEdges(borderPathType, out edgex, out edgey);

                IEnumerable<Hex> hexes =
                    Util.Sequence(1, Astrometrics.SectorWidth).Select(x => new Hex((byte)x, 1))
                    .Concat(Util.Sequence(2, Astrometrics.SectorHeight).Select(y => new Hex(Astrometrics.SectorWidth, (byte)y)))
                    .Concat(Util.Sequence(Astrometrics.SectorWidth - 1, 1).Select(x => new Hex((byte)x, Astrometrics.SectorHeight)))
                    .Concat(Util.Sequence(Astrometrics.SectorHeight - 1, 1).Select(y => new Hex(1, (byte)y)));

                Rectangle bounds = sector.Bounds;
                IEnumerable<Point> points = (from hex in hexes select new Point(hex.X + bounds.X, hex.Y + bounds.Y)).ToList();
                PathUtil.ComputeBorderPath(points, edgex, edgey, out clipPathPoints, out clipPathPointTypes);

                PointF min = clipPathPoints[0];
                PointF max = clipPathPoints[0];
                for (int i = 1; i < clipPathPoints.Length; ++i)
                {
                    PointF pt = clipPathPoints[i];
                    if (pt.X < min.X)
                        min.X = pt.X;
                    if (pt.Y < min.Y)
                        min.Y = pt.Y;
                    if (pt.X > max.X)
                        max.X = pt.X;
                    if (pt.Y > max.Y)
                        max.Y = pt.Y;
                }
                this.bounds = new RectangleF(min, new SizeF(max.X - min.X, max.Y - min.Y));
            }
Example #6
0
        public BorderPath(Border border, Sector sector, PathUtil.PathType type)
        {
            float[] edgeX, edgeY;
            RenderUtil.HexEdges(type, out edgeX, out edgeY);

            int lengthEstimate = border.Path.Count() * 3;

            List<PointF> points = new List<PointF>(lengthEstimate);
            List<byte> types = new List<byte>(lengthEstimate);
            LinkedList<LinkedList<PointF>> segments = new LinkedList<LinkedList<PointF>>();
            LinkedList<PointF> currentSegment = new LinkedList<PointF>();

            // Based on http://dotclue.org/t20/sec2pdf - J Greely rocks my world.

            int checkFirst = 0;
            int checkLast = 5;

            Hex startHex = Hex.Empty;
            bool startHexVisited = false;

            foreach (Hex hex in border.Path)
            {
                checkLast = checkFirst + 5;

                if (startHexVisited && hex == startHex)
                {
                    // I'm in the starting hex, and I've been
                    // there before, so stop testing at neighbor
                    // 5, no matter what
                    checkLast = 5;

                    // degenerate case, entering for third time
                    if (checkFirst < 3)
                        break;
                }
                else if (!startHexVisited)
                {
                    startHex = hex;
                    startHexVisited = true;

                    // PERF: This seems costly... analyze it!
                    PointF newPoint = Astrometrics.HexToCenter(Astrometrics.LocationToCoordinates(new Location(sector.Location, hex)));
                    newPoint.X += edgeX[0];
                    newPoint.Y += edgeY[0];

                    // MOVETO
                    points.Add(newPoint);
                    types.Add((byte)PathPointType.Start);

                    // MOVETO
                    currentSegment.AddLast(newPoint);
                }

                PointF pt = Astrometrics.HexToCenter(Astrometrics.LocationToCoordinates(new Location(sector.Location, hex)));

                int i = checkFirst;
                for (int check = checkFirst; check <= checkLast; check++)
                {
                    i = check;
                    Hex neighbor = Astrometrics.HexNeighbor(hex, i % 6);

                    if (border.Path.Contains(neighbor)) // TODO: Consider a hash here
                        break;

                    PointF newPoint = new PointF(pt.X + edgeX[(i + 1) % 6], pt.Y + edgeY[(i + 1) % 6]);

                    // LINETO
                    points.Add(newPoint);
                    types.Add((byte)PathPointType.Line);

                    if (hex.IsValid)
                    {
                        // MOVETO
                        currentSegment.AddLast(newPoint);
                    }
                    else
                    {
                        // LINETO
                        if (currentSegment.Count > 1)
                            segments.AddLast(currentSegment);
                        currentSegment = new LinkedList<PointF>();
                        currentSegment.AddLast(newPoint);
                    }

                }
                i = i % 6;
                // i is the direction to the next border hex,
                // and when we get there, we'll have come from
                // i + 3, so we start checking with i + 4.
                checkFirst = (i + 4) % 6;
            }

            types[types.Count - 1] |= (byte)PathPointType.CloseSubpath;

            if (currentSegment.Count > 1)
                segments.AddLast(currentSegment);

            this.points = points.ToArray();
            this.types = types.ToArray();

            // If last curve segment connects to first curve segment, merge them.
            // Example: Imperial border in Verge.
            if (segments.Count >= 2 && segments.First().First() == segments.Last().Last())
            {
                var first = segments.First();
                var last = segments.Last();
                segments.RemoveFirst();
                first.RemoveFirst();
                foreach (var point in first)
                    last.AddLast(point);
            }

            this.curves = segments.Select(c =>
            {
                if (c.First() == c.Last())
                {
                    c.RemoveLast();
                    return new CurveSegment(c, true);
                }
                else
                {
                    return new CurveSegment(c, false);
                }
            }).ToList();
        }