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; } } } }
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); }