public void DistanceToPseudoDistance(ref SignedDistance distance, Vector2 origin, double t) { if (t < 0) { Vector2 dir = Vector2.Normalize(GetDirection(0)); Vector2 aq = origin - GetPoint(0); double ts = Vector2.Dot(aq, dir); if (ts < 0) { double pseudoDistance = Cross(aq, dir); if (Math.Abs(pseudoDistance) <= Math.Abs(distance.distance)) { distance.distance = pseudoDistance; distance.dot = 0; } } } else if (t > 1) { Vector2 dir = Vector2.Normalize(GetDirection(1)); Vector2 bq = origin - GetPoint(1); double ts = Vector2.Dot(bq, dir); if (ts > 0) { double pseudoDistance = Cross(bq, dir); if (Math.Abs(pseudoDistance) <= Math.Abs(distance.distance)) { distance.distance = pseudoDistance; distance.dot = 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)); }
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); }