Beispiel #1
0
        static Color3 EvaluateMSDF(Shape shape, int[] windings, MultiDistance[] contourSD, Vector2 p, double range)
        {
            int contourCount = contourSD.Length;

            p += new Vector2(0.5f, 0.5f);

            EdgePoint sr = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };
            EdgePoint sg = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };
            EdgePoint sb = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };

            double d       = Math.Abs(SignedDistance.Infinite.distance);
            double negDist = -SignedDistance.Infinite.distance;
            double posDist = SignedDistance.Infinite.distance;
            int    winding = 0;

            for (int i = 0; i < contourCount; i++)
            {
                Contour   contour = shape.Contours[i];
                EdgePoint r       = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };
                EdgePoint g = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };
                EdgePoint b = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };

                for (int j = 0; j < contour.Edges.Count; j++)
                {
                    EdgeSegment edge = contour.Edges[j];
                    double      param;

                    SignedDistance distance = edge.GetSignedDistance(p, out param);
                    if ((edge.Color & EdgeColor.Red) == EdgeColor.Red && distance < r.minDistance)
                    {
                        r.minDistance = distance;
                        r.nearEdge    = edge;
                        r.nearParam   = param;
                    }
                    if ((edge.Color & EdgeColor.Green) == EdgeColor.Green && distance < g.minDistance)
                    {
                        g.minDistance = distance;
                        g.nearEdge    = edge;
                        g.nearParam   = param;
                    }
                    if ((edge.Color & EdgeColor.Blue) == EdgeColor.Blue && distance < b.minDistance)
                    {
                        b.minDistance = distance;
                        b.nearEdge    = edge;
                        b.nearParam   = param;
                    }
                }

                if (r.minDistance < sr.minDistance)
                {
                    sr = r;
                }
                if (g.minDistance < sg.minDistance)
                {
                    sg = g;
                }
                if (b.minDistance < sb.minDistance)
                {
                    sb = b;
                }

                double medMinDistance = Math.Abs(Median(r.minDistance.distance, g.minDistance.distance, b.minDistance.distance));

                if (medMinDistance < d)
                {
                    d       = medMinDistance;
                    winding = -windings[i];
                }

                if (r.nearEdge != null)
                {
                    r.nearEdge.DistanceToPseudoDistance(ref r.minDistance, p, r.nearParam);
                }
                if (g.nearEdge != null)
                {
                    g.nearEdge.DistanceToPseudoDistance(ref g.minDistance, p, g.nearParam);
                }
                if (b.nearEdge != null)
                {
                    b.nearEdge.DistanceToPseudoDistance(ref b.minDistance, p, b.nearParam);
                }

                medMinDistance = Median(r.minDistance.distance, g.minDistance.distance, b.minDistance.distance);

                contourSD[i].r   = r.minDistance.distance;
                contourSD[i].g   = g.minDistance.distance;
                contourSD[i].b   = b.minDistance.distance;
                contourSD[i].med = medMinDistance;

                if (windings[i] > 0 && medMinDistance >= 0 && Math.Abs(medMinDistance) < Math.Abs(posDist))
                {
                    posDist = medMinDistance;
                }
                if (windings[i] < 0 && medMinDistance <= 0 && Math.Abs(medMinDistance) < Math.Abs(negDist))
                {
                    negDist = medMinDistance;
                }
            }

            if (sr.nearEdge != null)
            {
                sr.nearEdge.DistanceToPseudoDistance(ref sr.minDistance, p, sr.nearParam);
            }
            if (sg.nearEdge != null)
            {
                sg.nearEdge.DistanceToPseudoDistance(ref sg.minDistance, p, sg.nearParam);
            }
            if (sb.nearEdge != null)
            {
                sb.nearEdge.DistanceToPseudoDistance(ref sb.minDistance, p, sb.nearParam);
            }

            MultiDistance msd = new MultiDistance {
                r   = SignedDistance.Infinite.distance,
                g   = SignedDistance.Infinite.distance,
                b   = SignedDistance.Infinite.distance,
                med = SignedDistance.Infinite.distance,
            };

            if (posDist >= 0 && Math.Abs(posDist) <= Math.Abs(negDist))
            {
                msd.med = SignedDistance.Infinite.distance;
                winding = 1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] > 0 && contourSD[i].med > msd.med && Math.Abs(contourSD[i].med) < Math.Abs(negDist))
                    {
                        msd = contourSD[i];
                    }
                }
            }
            else if (negDist <= 0 && Math.Abs(negDist) <= Math.Abs(posDist))
            {
                msd.med = -SignedDistance.Infinite.distance;
                winding = -1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] < 0 && contourSD[i].med < msd.med && Math.Abs(contourSD[i].med) < Math.Abs(posDist))
                    {
                        msd = contourSD[i];
                    }
                }
            }

            for (int i = 0; i < contourCount; i++)
            {
                if (windings[i] != winding && Math.Abs(contourSD[i].med) < Math.Abs(msd.med))
                {
                    msd = contourSD[i];
                }
            }

            if (Median(sr.minDistance.distance, sg.minDistance.distance, sb.minDistance.distance) == msd.med)
            {
                msd.r = sr.minDistance.distance;
                msd.g = sg.minDistance.distance;
                msd.b = sb.minDistance.distance;
            }

            return(new Color3((float)(msd.r / range) + 0.5f, (float)(msd.g / range) + 0.5f, (float)(msd.b / range) + 0.5f));
        }
        public static void EdgeColoringSimple(Shape shape, double angleThreshold, ulong seed)
        {
            double     crossThreshold = Math.Sin(angleThreshold);
            List <int> corners        = new List <int>();

            for (int i = 0; i < shape.Contours.Count; i++)
            {
                Contour contour = shape.Contours[i];
                corners.Clear();

                if (!(contour.Edges.Count == 0))
                {
                    Vector2 prevDirection = contour.Edges[contour.Edges.Count - 1].GetDirection(1);

                    for (int j = 0; j < contour.Edges.Count; j++)
                    {
                        EdgeSegment edge = contour.Edges[j];
                        if (IsCorner(Vector2.Normalize(prevDirection), Vector2.Normalize(edge.GetDirection(0)), crossThreshold))
                        {
                            corners.Add(j);
                        }
                        prevDirection = edge.GetDirection(1);
                    }
                }

                if (corners.Count == 0)
                {
                    for (int j = 0; j < contour.Edges.Count; j++)
                    {
                        contour.Edges[j].Color = EdgeColor.White;
                    }
                }
                else if (corners.Count == 1)
                {
                    EdgeColor[] colors = { EdgeColor.White, EdgeColor.White, EdgeColor.Black };
                    SwitchColor(ref colors[0], ref seed, EdgeColor.Black);
                    SwitchColor(ref colors[2], ref seed, EdgeColor.Black);

                    int corner = corners[0];

                    if (contour.Edges.Count >= 3)
                    {
                        int m = contour.Edges.Count;
                        for (int j = 0; j < m; j++)
                        {
                            int magic = (int)(3 + 2.875f * j / (m - 1) - 1.4375f + 0.5f) - 3;   //see edge-coloring.cpp in the original msdfgen
                            contour.Edges[(corner + j) % m].Color = colors[1 + magic];
                        }
                    }
                    else if (contour.Edges.Count >= 1)
                    {
                        EdgeSegment[] parts = new EdgeSegment[7];
                        contour.Edges[0].SplitInThirds(out parts[0 + 3 * corner], out parts[1 + 3 * corner], out parts[2 + 3 * corner]);
                        if (contour.Edges.Count >= 2)
                        {
                            contour.Edges[1].SplitInThirds(out parts[3 - 3 * corner], out parts[4 - 3 * corner], out parts[5 - 3 * corner]);
                            parts[0].Color = colors[0];
                            parts[1].Color = colors[0];
                            parts[2].Color = colors[1];
                            parts[3].Color = colors[1];
                            parts[4].Color = colors[2];
                            parts[5].Color = colors[2];
                        }
                        else
                        {
                            parts[0].Color = colors[0];
                            parts[1].Color = colors[1];
                            parts[2].Color = colors[2];
                        }
                        contour.Edges.Clear();
                        for (int j = 0; parts[j] != null; j++)
                        {
                            contour.Edges.Add(parts[j]);
                        }
                    }
                }
                else
                {
                    int       cornerCount = corners.Count;
                    int       spline      = 0;
                    int       start       = corners[0];
                    int       m           = contour.Edges.Count;
                    EdgeColor color       = EdgeColor.White;
                    SwitchColor(ref color, ref seed, EdgeColor.Black);
                    EdgeColor initialColor = color;
                    for (int j = 0; j < m; j++)
                    {
                        int index = (start + j) % m;
                        if (spline + 1 < cornerCount && corners[spline + 1] == index)
                        {
                            spline++;
                            SwitchColor(ref color, ref seed, (EdgeColor)(((spline == cornerCount - 1) ? 1 : 0) * (int)initialColor));
                        }
                        contour.Edges[index].Color = color;
                    }
                }
            }
        }
Beispiel #3
0
        static float EvaluateSDF(Shape shape, int[] windings, double[] contourSD, int x, int y, double range, Vector2 scale, Vector2 translate)
        {
            int contourCount = contourSD.Length;

            double  dummy;
            Vector2 p       = new Vector2(x + 0.5f, y + 0.5f) / scale - translate;
            double  negDist = -SignedDistance.Infinite.distance;
            double  posDist = SignedDistance.Infinite.distance;
            int     winding = 0;

            for (int i = 0; i < contourCount; i++)
            {
                Contour        contour     = shape.Contours[i];
                SignedDistance minDistance = new SignedDistance(-1e240, 1);

                for (int j = 0; j < contour.Edges.Count; j++)
                {
                    EdgeSegment    edge     = contour.Edges[j];
                    SignedDistance distance = edge.GetSignedDistance(p, out dummy);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                    }
                }

                contourSD[i] = minDistance.distance;
                if (windings[i] > 0 && minDistance.distance >= 0 && Math.Abs(minDistance.distance) < Math.Abs(posDist))
                {
                    posDist = minDistance.distance;
                }

                if (windings[i] < 0 && minDistance.distance <= 0 && Math.Abs(minDistance.distance) < Math.Abs(negDist))
                {
                    negDist = minDistance.distance;
                }
            }

            double sd = SignedDistance.Infinite.distance;

            if (posDist >= 0 && Math.Abs(posDist) <= Math.Abs(negDist))
            {
                sd      = posDist;
                winding = 1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] > 0 && contourSD[i] > sd && Math.Abs(contourSD[i]) < Math.Abs(negDist))
                    {
                        sd = contourSD[i];
                    }
                }
            }
            else if (negDist <= 0 && Math.Abs(negDist) <= Math.Abs(posDist))
            {
                sd      = negDist;
                winding = -1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] < 0 && contourSD[i] < sd && Math.Abs(contourSD[i]) < Math.Abs(posDist))
                    {
                        sd = contourSD[i];
                    }
                }
            }

            for (int i = 0; i < contourCount; i++)
            {
                if (windings[i] != winding && Math.Abs(contourSD[i]) < Math.Abs(sd))
                {
                    sd = contourSD[i];
                }
            }

            return((float)(sd / range) + 0.5f);
        }