فهرست منبع

Renamed pseudo-distance to perpendicular distance

Chlumsky 1 سال پیش
والد
کامیت
64c3e24829
10فایلهای تغییر یافته به همراه129 افزوده شده و 111 حذف شده
  1. 5 6
      README.md
  2. 1 1
      core/MSDFErrorCorrection.cpp
  3. 2 2
      core/contour-combiners.cpp
  4. 7 7
      core/edge-segments.cpp
  5. 2 2
      core/edge-segments.h
  6. 51 51
      core/edge-selectors.cpp
  7. 14 14
      core/edge-selectors.h
  8. 24 12
      core/msdfgen.cpp
  9. 17 14
      main.cpp
  10. 6 2
      msdfgen.h

+ 5 - 6
README.md

@@ -4,7 +4,7 @@ This is a utility for generating signed distance fields from vector shapes and f
 which serve as a texture representation that can be used in real-time graphics to efficiently reproduce said shapes.
 Although it can also be used to generate conventional signed distance fields best known from
 [this Valve paper](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf)
-and pseudo-distance fields, its primary purpose is to generate multi-channel distance fields,
+and perpendicular distance fields, its primary purpose is to generate multi-channel distance fields,
 using a method I have developed. Unlike monochrome distance fields, they have the ability
 to reproduce sharp corners almost perfectly by utilizing all three color channels.
 
@@ -52,7 +52,7 @@ where only the input specification is required.
 
 Mode can be one of:
  - **sdf** – generates a conventional monochrome (true) signed distance field.
- - **psdf** – generates a monochrome signed pseudo-distance field.
+ - **psdf** – generates a monochrome signed perpendicular distance field.
  - **msdf** (default) – generates a multi-channel signed distance field using my new method.
  - **mtsdf** – generates a combined multi-channel and true signed distance field in the alpha channel.
 
@@ -104,10 +104,9 @@ in order to generate a distance field. Please note that all classes and function
    It consists of closed contours, which in turn consist of edges. An edge is represented by a `LinearEdge`, `QuadraticEdge`,
    or `CubicEdge`. You can construct them from two endpoints and 0 to 2 Bézier control points.
  - Normalize the shape using its `normalize` method and assign colors to edges if you need a multi-channel SDF.
-   This can be performed automatically using the `edgeColoringSimple` heuristic, or manually by setting each edge's
-   `color` member. Keep in mind that at least two color channels must be turned on in each edge, and iff two edges meet
-   at a sharp corner, they must only have one channel in common.
- - Call `generateSDF`, `generatePseudoSDF`, or `generateMSDF` to generate a distance field into a floating point
+   This can be performed automatically using the `edgeColoringSimple` (or other) heuristic, or manually by setting each edge's
+   `color` member. Keep in mind that at least two color channels must be turned on in each edge.
+ - Call `generateSDF`, `generatePSDF`, `generateMSDF`, or `generateMTSDF` to generate a distance field into a floating point
    `Bitmap` object. This can then be worked with further or saved to a file using `saveBmp`, `savePng`, or `saveTiff`.
  - You may also render an image from the distance field using `renderSDF`. Consider calling `simulate8bit`
    on the distance field beforehand to simulate the standard 8 bits/channel image format.

+ 1 - 1
core/MSDFErrorCorrection.cpp

@@ -94,7 +94,7 @@ public:
         return ArtifactClassifier(this, direction, span);
     }
 private:
-    ShapeDistanceFinder<ContourCombiner<PseudoDistanceSelector> > distanceFinder;
+    ShapeDistanceFinder<ContourCombiner<PerpendicularDistanceSelector> > distanceFinder;
     BitmapConstRef<float, N> sdf;
     double invRange;
     Vector2 texelSize;

+ 2 - 2
core/contour-combiners.cpp

@@ -50,7 +50,7 @@ typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner
 }
 
 template class SimpleContourCombiner<TrueDistanceSelector>;
-template class SimpleContourCombiner<PseudoDistanceSelector>;
+template class SimpleContourCombiner<PerpendicularDistanceSelector>;
 template class SimpleContourCombiner<MultiDistanceSelector>;
 template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
 
@@ -134,7 +134,7 @@ typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingConto
 }
 
 template class OverlappingContourCombiner<TrueDistanceSelector>;
-template class OverlappingContourCombiner<PseudoDistanceSelector>;
+template class OverlappingContourCombiner<PerpendicularDistanceSelector>;
 template class OverlappingContourCombiner<MultiDistanceSelector>;
 template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
 

+ 7 - 7
core/edge-segments.cpp

@@ -25,15 +25,15 @@ EdgeSegment *EdgeSegment::create(Point2 p0, Point2 p1, Point2 p2, Point2 p3, Edg
     return new CubicSegment(p0, p1, p2, p3, edgeColor);
 }
 
-void EdgeSegment::distanceToPseudoDistance(SignedDistance &distance, Point2 origin, double param) const {
+void EdgeSegment::distanceToPerpendicularDistance(SignedDistance &distance, Point2 origin, double param) const {
     if (param < 0) {
         Vector2 dir = direction(0).normalize();
         Vector2 aq = origin-point(0);
         double ts = dotProduct(aq, dir);
         if (ts < 0) {
-            double pseudoDistance = crossProduct(aq, dir);
-            if (fabs(pseudoDistance) <= fabs(distance.distance)) {
-                distance.distance = pseudoDistance;
+            double perpendicularDistance = crossProduct(aq, dir);
+            if (fabs(perpendicularDistance) <= fabs(distance.distance)) {
+                distance.distance = perpendicularDistance;
                 distance.dot = 0;
             }
         }
@@ -42,9 +42,9 @@ void EdgeSegment::distanceToPseudoDistance(SignedDistance &distance, Point2 orig
         Vector2 bq = origin-point(1);
         double ts = dotProduct(bq, dir);
         if (ts > 0) {
-            double pseudoDistance = crossProduct(bq, dir);
-            if (fabs(pseudoDistance) <= fabs(distance.distance)) {
-                distance.distance = pseudoDistance;
+            double perpendicularDistance = crossProduct(bq, dir);
+            if (fabs(perpendicularDistance) <= fabs(distance.distance)) {
+                distance.distance = perpendicularDistance;
                 distance.dot = 0;
             }
         }

+ 2 - 2
core/edge-segments.h

@@ -37,8 +37,8 @@ public:
     virtual Vector2 directionChange(double param) const = 0;
     /// Returns the minimum signed distance between origin and the edge.
     virtual SignedDistance signedDistance(Point2 origin, double &param) const = 0;
-    /// Converts a previously retrieved signed distance from origin to pseudo-distance.
-    virtual void distanceToPseudoDistance(SignedDistance &distance, Point2 origin, double param) const;
+    /// Converts a previously retrieved signed distance from origin to perpendicular distance.
+    virtual void distanceToPerpendicularDistance(SignedDistance &distance, Point2 origin, double param) const;
     /// Outputs a list of (at most three) intersections (their X coordinates) with an infinite horizontal scanline at y and returns how many there are.
     virtual int scanlineIntersections(double x[3], int dy[3], double y) const = 0;
     /// Adjusts the bounding box to fit the edge segment.

+ 51 - 51
core/edge-selectors.cpp

@@ -36,48 +36,48 @@ TrueDistanceSelector::DistanceType TrueDistanceSelector::distance() const {
     return minDistance.distance;
 }
 
-PseudoDistanceSelectorBase::EdgeCache::EdgeCache() : absDistance(0), aDomainDistance(0), bDomainDistance(0), aPseudoDistance(0), bPseudoDistance(0) { }
+PerpendicularDistanceSelectorBase::EdgeCache::EdgeCache() : absDistance(0), aDomainDistance(0), bDomainDistance(0), aPerpendicularDistance(0), bPerpendicularDistance(0) { }
 
-bool PseudoDistanceSelectorBase::getPseudoDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir) {
+bool PerpendicularDistanceSelectorBase::getPerpendicularDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir) {
     double ts = dotProduct(ep, edgeDir);
     if (ts > 0) {
-        double pseudoDistance = crossProduct(ep, edgeDir);
-        if (fabs(pseudoDistance) < fabs(distance)) {
-            distance = pseudoDistance;
+        double perpendicularDistance = crossProduct(ep, edgeDir);
+        if (fabs(perpendicularDistance) < fabs(distance)) {
+            distance = perpendicularDistance;
             return true;
         }
     }
     return false;
 }
 
-PseudoDistanceSelectorBase::PseudoDistanceSelectorBase() : minNegativePseudoDistance(-fabs(minTrueDistance.distance)), minPositivePseudoDistance(fabs(minTrueDistance.distance)), nearEdge(NULL), nearEdgeParam(0) { }
+PerpendicularDistanceSelectorBase::PerpendicularDistanceSelectorBase() : minNegativePerpendicularDistance(-fabs(minTrueDistance.distance)), minPositivePerpendicularDistance(fabs(minTrueDistance.distance)), nearEdge(NULL), nearEdgeParam(0) { }
 
-void PseudoDistanceSelectorBase::reset(double delta) {
+void PerpendicularDistanceSelectorBase::reset(double delta) {
     minTrueDistance.distance += nonZeroSign(minTrueDistance.distance)*delta;
-    minNegativePseudoDistance = -fabs(minTrueDistance.distance);
-    minPositivePseudoDistance = fabs(minTrueDistance.distance);
+    minNegativePerpendicularDistance = -fabs(minTrueDistance.distance);
+    minPositivePerpendicularDistance = fabs(minTrueDistance.distance);
     nearEdge = NULL;
     nearEdgeParam = 0;
 }
 
-bool PseudoDistanceSelectorBase::isEdgeRelevant(const EdgeCache &cache, const EdgeSegment *edge, const Point2 &p) const {
+bool PerpendicularDistanceSelectorBase::isEdgeRelevant(const EdgeCache &cache, const EdgeSegment *edge, const Point2 &p) const {
     double delta = DISTANCE_DELTA_FACTOR*(p-cache.point).length();
     return (
         cache.absDistance-delta <= fabs(minTrueDistance.distance) ||
         fabs(cache.aDomainDistance) < delta ||
         fabs(cache.bDomainDistance) < delta ||
-        (cache.aDomainDistance > 0 && (cache.aPseudoDistance < 0 ?
-            cache.aPseudoDistance+delta >= minNegativePseudoDistance :
-            cache.aPseudoDistance-delta <= minPositivePseudoDistance
+        (cache.aDomainDistance > 0 && (cache.aPerpendicularDistance < 0 ?
+            cache.aPerpendicularDistance+delta >= minNegativePerpendicularDistance :
+            cache.aPerpendicularDistance-delta <= minPositivePerpendicularDistance
         )) ||
-        (cache.bDomainDistance > 0 && (cache.bPseudoDistance < 0 ?
-            cache.bPseudoDistance+delta >= minNegativePseudoDistance :
-            cache.bPseudoDistance-delta <= minPositivePseudoDistance
+        (cache.bDomainDistance > 0 && (cache.bPerpendicularDistance < 0 ?
+            cache.bPerpendicularDistance+delta >= minNegativePerpendicularDistance :
+            cache.bPerpendicularDistance-delta <= minPositivePerpendicularDistance
         ))
     );
 }
 
-void PseudoDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param) {
+void PerpendicularDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param) {
     if (distance < minTrueDistance) {
         minTrueDistance = distance;
         nearEdge = edge;
@@ -85,47 +85,47 @@ void PseudoDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, co
     }
 }
 
-void PseudoDistanceSelectorBase::addEdgePseudoDistance(double distance) {
-    if (distance <= 0 && distance > minNegativePseudoDistance)
-        minNegativePseudoDistance = distance;
-    if (distance >= 0 && distance < minPositivePseudoDistance)
-        minPositivePseudoDistance = distance;
+void PerpendicularDistanceSelectorBase::addEdgePerpendicularDistance(double distance) {
+    if (distance <= 0 && distance > minNegativePerpendicularDistance)
+        minNegativePerpendicularDistance = distance;
+    if (distance >= 0 && distance < minPositivePerpendicularDistance)
+        minPositivePerpendicularDistance = distance;
 }
 
-void PseudoDistanceSelectorBase::merge(const PseudoDistanceSelectorBase &other) {
+void PerpendicularDistanceSelectorBase::merge(const PerpendicularDistanceSelectorBase &other) {
     if (other.minTrueDistance < minTrueDistance) {
         minTrueDistance = other.minTrueDistance;
         nearEdge = other.nearEdge;
         nearEdgeParam = other.nearEdgeParam;
     }
-    if (other.minNegativePseudoDistance > minNegativePseudoDistance)
-        minNegativePseudoDistance = other.minNegativePseudoDistance;
-    if (other.minPositivePseudoDistance < minPositivePseudoDistance)
-        minPositivePseudoDistance = other.minPositivePseudoDistance;
+    if (other.minNegativePerpendicularDistance > minNegativePerpendicularDistance)
+        minNegativePerpendicularDistance = other.minNegativePerpendicularDistance;
+    if (other.minPositivePerpendicularDistance < minPositivePerpendicularDistance)
+        minPositivePerpendicularDistance = other.minPositivePerpendicularDistance;
 }
 
-double PseudoDistanceSelectorBase::computeDistance(const Point2 &p) const {
-    double minDistance = minTrueDistance.distance < 0 ? minNegativePseudoDistance : minPositivePseudoDistance;
+double PerpendicularDistanceSelectorBase::computeDistance(const Point2 &p) const {
+    double minDistance = minTrueDistance.distance < 0 ? minNegativePerpendicularDistance : minPositivePerpendicularDistance;
     if (nearEdge) {
         SignedDistance distance = minTrueDistance;
-        nearEdge->distanceToPseudoDistance(distance, p, nearEdgeParam);
+        nearEdge->distanceToPerpendicularDistance(distance, p, nearEdgeParam);
         if (fabs(distance.distance) < fabs(minDistance))
             minDistance = distance.distance;
     }
     return minDistance;
 }
 
-SignedDistance PseudoDistanceSelectorBase::trueDistance() const {
+SignedDistance PerpendicularDistanceSelectorBase::trueDistance() const {
     return minTrueDistance;
 }
 
-void PseudoDistanceSelector::reset(const Point2 &p) {
+void PerpendicularDistanceSelector::reset(const Point2 &p) {
     double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();
-    PseudoDistanceSelectorBase::reset(delta);
+    PerpendicularDistanceSelectorBase::reset(delta);
     this->p = p;
 }
 
-void PseudoDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
+void PerpendicularDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
     if (isEdgeRelevant(cache, edge, p)) {
         double param;
         SignedDistance distance = edge->signedDistance(p, param);
@@ -143,22 +143,22 @@ void PseudoDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEd
         double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));
         if (add > 0) {
             double pd = distance.distance;
-            if (getPseudoDistance(pd, ap, -aDir))
-                addEdgePseudoDistance(pd = -pd);
-            cache.aPseudoDistance = pd;
+            if (getPerpendicularDistance(pd, ap, -aDir))
+                addEdgePerpendicularDistance(pd = -pd);
+            cache.aPerpendicularDistance = pd;
         }
         if (bdd > 0) {
             double pd = distance.distance;
-            if (getPseudoDistance(pd, bp, bDir))
-                addEdgePseudoDistance(pd);
-            cache.bPseudoDistance = pd;
+            if (getPerpendicularDistance(pd, bp, bDir))
+                addEdgePerpendicularDistance(pd);
+            cache.bPerpendicularDistance = pd;
         }
         cache.aDomainDistance = add;
         cache.bDomainDistance = bdd;
     }
 }
 
-PseudoDistanceSelector::DistanceType PseudoDistanceSelector::distance() const {
+PerpendicularDistanceSelector::DistanceType PerpendicularDistanceSelector::distance() const {
     return computeDistance(p);
 }
 
@@ -197,28 +197,28 @@ void MultiDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdg
         double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));
         if (add > 0) {
             double pd = distance.distance;
-            if (PseudoDistanceSelectorBase::getPseudoDistance(pd, ap, -aDir)) {
+            if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, ap, -aDir)) {
                 pd = -pd;
                 if (edge->color&RED)
-                    r.addEdgePseudoDistance(pd);
+                    r.addEdgePerpendicularDistance(pd);
                 if (edge->color&GREEN)
-                    g.addEdgePseudoDistance(pd);
+                    g.addEdgePerpendicularDistance(pd);
                 if (edge->color&BLUE)
-                    b.addEdgePseudoDistance(pd);
+                    b.addEdgePerpendicularDistance(pd);
             }
-            cache.aPseudoDistance = pd;
+            cache.aPerpendicularDistance = pd;
         }
         if (bdd > 0) {
             double pd = distance.distance;
-            if (PseudoDistanceSelectorBase::getPseudoDistance(pd, bp, bDir)) {
+            if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, bp, bDir)) {
                 if (edge->color&RED)
-                    r.addEdgePseudoDistance(pd);
+                    r.addEdgePerpendicularDistance(pd);
                 if (edge->color&GREEN)
-                    g.addEdgePseudoDistance(pd);
+                    g.addEdgePerpendicularDistance(pd);
                 if (edge->color&BLUE)
-                    b.addEdgePseudoDistance(pd);
+                    b.addEdgePerpendicularDistance(pd);
             }
-            cache.bPseudoDistance = pd;
+            cache.bPerpendicularDistance = pd;
         }
         cache.aDomainDistance = add;
         cache.bDomainDistance = bdd;

+ 14 - 14
core/edge-selectors.h

@@ -38,40 +38,40 @@ private:
 
 };
 
-class PseudoDistanceSelectorBase {
+class PerpendicularDistanceSelectorBase {
 
 public:
     struct EdgeCache {
         Point2 point;
         double absDistance;
         double aDomainDistance, bDomainDistance;
-        double aPseudoDistance, bPseudoDistance;
+        double aPerpendicularDistance, bPerpendicularDistance;
 
         EdgeCache();
     };
 
-    static bool getPseudoDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir);
+    static bool getPerpendicularDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir);
 
-    PseudoDistanceSelectorBase();
+    PerpendicularDistanceSelectorBase();
     void reset(double delta);
     bool isEdgeRelevant(const EdgeCache &cache, const EdgeSegment *edge, const Point2 &p) const;
     void addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param);
-    void addEdgePseudoDistance(double distance);
-    void merge(const PseudoDistanceSelectorBase &other);
+    void addEdgePerpendicularDistance(double distance);
+    void merge(const PerpendicularDistanceSelectorBase &other);
     double computeDistance(const Point2 &p) const;
     SignedDistance trueDistance() const;
 
 private:
     SignedDistance minTrueDistance;
-    double minNegativePseudoDistance;
-    double minPositivePseudoDistance;
+    double minNegativePerpendicularDistance;
+    double minPositivePerpendicularDistance;
     const EdgeSegment *nearEdge;
     double nearEdgeParam;
 
 };
 
-/// Selects the nearest edge by its pseudo-distance.
-class PseudoDistanceSelector : public PseudoDistanceSelectorBase {
+/// Selects the nearest edge by its perpendicular distance.
+class PerpendicularDistanceSelector : public PerpendicularDistanceSelectorBase {
 
 public:
     typedef double DistanceType;
@@ -85,12 +85,12 @@ private:
 
 };
 
-/// Selects the nearest edge for each of the three channels by its pseudo-distance.
+/// Selects the nearest edge for each of the three channels by its perpendicular distance.
 class MultiDistanceSelector {
 
 public:
     typedef MultiDistance DistanceType;
-    typedef PseudoDistanceSelectorBase::EdgeCache EdgeCache;
+    typedef PerpendicularDistanceSelectorBase::EdgeCache EdgeCache;
 
     void reset(const Point2 &p);
     void addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge);
@@ -100,11 +100,11 @@ public:
 
 private:
     Point2 p;
-    PseudoDistanceSelectorBase r, g, b;
+    PerpendicularDistanceSelectorBase r, g, b;
 
 };
 
-/// Selects the nearest edge for each of the three color channels by its pseudo-distance and by true distance for the alpha channel.
+/// Selects the nearest edge for each of the three color channels by its perpendicular distance and by true distance for the alpha channel.
 class MultiAndTrueDistanceSelector : public MultiDistanceSelector {
 
 public:

+ 24 - 12
core/msdfgen.cpp

@@ -81,11 +81,11 @@ void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Pr
         generateDistanceField<SimpleContourCombiner<TrueDistanceSelector> >(output, shape, projection, range);
 }
 
-void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config) {
+void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config) {
     if (config.overlapSupport)
-        generateDistanceField<OverlappingContourCombiner<PseudoDistanceSelector> >(output, shape, projection, range);
+        generateDistanceField<OverlappingContourCombiner<PerpendicularDistanceSelector> >(output, shape, projection, range);
     else
-        generateDistanceField<SimpleContourCombiner<PseudoDistanceSelector> >(output, shape, projection, range);
+        generateDistanceField<SimpleContourCombiner<PerpendicularDistanceSelector> >(output, shape, projection, range);
 }
 
 void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, const Projection &projection, double range, const MSDFGeneratorConfig &config) {
@@ -106,12 +106,20 @@ void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, const
 
 // Legacy API
 
+void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config) {
+    generatePSDF(output, shape, projection, range, config);
+}
+
 void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
     generateSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));
 }
 
+void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
+    generatePSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));
+}
+
 void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport) {
-    generatePseudoSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));
+    generatePSDF(output, shape, Projection(scale, translate), range, GeneratorConfig(overlapSupport));
 }
 
 void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, const ErrorCorrectionConfig &errorCorrectionConfig, bool overlapSupport) {
@@ -145,7 +153,7 @@ void generateSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, d
     }
 }
 
-void generatePseudoSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
+void generatePSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
 #ifdef MSDFGEN_USE_OPENMP
     #pragma omp parallel for
 #endif
@@ -167,12 +175,16 @@ void generatePseudoSDF_legacy(const BitmapRef<float, 1> &output, const Shape &sh
                     }
                 }
             if (nearEdge)
-                (*nearEdge)->distanceToPseudoDistance(minDistance, p, nearParam);
+                (*nearEdge)->distanceToPerpendicularDistance(minDistance, p, nearParam);
             *output(x, row) = float(minDistance.distance/range+.5);
         }
     }
 }
 
+void generatePseudoSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate) {
+    generatePSDF_legacy(output, shape, range, scale, translate);
+}
+
 void generateMSDF_legacy(const BitmapRef<float, 3> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, ErrorCorrectionConfig errorCorrectionConfig) {
 #ifdef MSDFGEN_USE_OPENMP
     #pragma omp parallel for
@@ -212,11 +224,11 @@ void generateMSDF_legacy(const BitmapRef<float, 3> &output, const Shape &shape,
                 }
 
             if (r.nearEdge)
-                (*r.nearEdge)->distanceToPseudoDistance(r.minDistance, p, r.nearParam);
+                (*r.nearEdge)->distanceToPerpendicularDistance(r.minDistance, p, r.nearParam);
             if (g.nearEdge)
-                (*g.nearEdge)->distanceToPseudoDistance(g.minDistance, p, g.nearParam);
+                (*g.nearEdge)->distanceToPerpendicularDistance(g.minDistance, p, g.nearParam);
             if (b.nearEdge)
-                (*b.nearEdge)->distanceToPseudoDistance(b.minDistance, p, b.nearParam);
+                (*b.nearEdge)->distanceToPerpendicularDistance(b.minDistance, p, b.nearParam);
             output(x, row)[0] = float(r.minDistance.distance/range+.5);
             output(x, row)[1] = float(g.minDistance.distance/range+.5);
             output(x, row)[2] = float(b.minDistance.distance/range+.5);
@@ -269,11 +281,11 @@ void generateMTSDF_legacy(const BitmapRef<float, 4> &output, const Shape &shape,
                 }
 
             if (r.nearEdge)
-                (*r.nearEdge)->distanceToPseudoDistance(r.minDistance, p, r.nearParam);
+                (*r.nearEdge)->distanceToPerpendicularDistance(r.minDistance, p, r.nearParam);
             if (g.nearEdge)
-                (*g.nearEdge)->distanceToPseudoDistance(g.minDistance, p, g.nearParam);
+                (*g.nearEdge)->distanceToPerpendicularDistance(g.minDistance, p, g.nearParam);
             if (b.nearEdge)
-                (*b.nearEdge)->distanceToPseudoDistance(b.minDistance, p, b.nearParam);
+                (*b.nearEdge)->distanceToPerpendicularDistance(b.minDistance, p, b.nearParam);
             output(x, row)[0] = float(r.minDistance.distance/range+.5);
             output(x, row)[1] = float(g.minDistance.distance/range+.5);
             output(x, row)[2] = float(b.minDistance.distance/range+.5);

+ 17 - 14
main.cpp

@@ -358,7 +358,7 @@ static const char *const helpText =
     "\n"
     "MODES\n"
     "  sdf - Generate conventional monochrome (true) signed distance field.\n"
-    "  psdf - Generate monochrome signed pseudo-distance field.\n"
+    "  psdf - Generate monochrome signed perpendicular distance field.\n"
     "  msdf - Generate multi-channel signed distance field. This is used by default if no mode is specified.\n"
     "  mtsdf - Generate combined multi-channel and true signed distance field in the alpha channel.\n"
     "  metrics - Report shape metrics only.\n"
@@ -513,7 +513,7 @@ int main(int argc, const char *const *argv) {
     } inputType = NONE;
     enum {
         SINGLE,
-        PSEUDO,
+        PERPENDICULAR,
         MULTI,
         MULTI_AND_TRUE,
         METRICS
@@ -573,7 +573,7 @@ int main(int argc, const char *const *argv) {
         GUESS
     } orientation = KEEP;
     unsigned long long coloringSeed = 0;
-    void (*edgeColoring)(Shape &, double, unsigned long long) = edgeColoringSimple;
+    void (*edgeColoring)(Shape &, double, unsigned long long) = &edgeColoringSimple;
     bool explicitErrorCorrectionMode = false;
 
     int argPos = 1;
@@ -589,7 +589,7 @@ int main(int argc, const char *const *argv) {
             ++arg;
 
         ARG_MODE("sdf", SINGLE)
-        ARG_MODE("psdf", PSEUDO)
+        ARG_MODE("psdf", PERPENDICULAR)
         ARG_MODE("msdf", MULTI)
         ARG_MODE("mtsdf", MULTI_AND_TRUE)
         ARG_MODE("metrics", METRICS)
@@ -856,9 +856,12 @@ int main(int argc, const char *const *argv) {
             continue;
         }
         ARG_CASE("-coloringstrategy", 1) {
-            if (!strcmp(argv[argPos+1], "simple")) edgeColoring = edgeColoringSimple;
-            else if (!strcmp(argv[argPos+1], "inktrap")) edgeColoring = edgeColoringInkTrap;
-            else if (!strcmp(argv[argPos+1], "distance")) edgeColoring = edgeColoringByDistance;
+            if (!strcmp(argv[argPos+1], "simple"))
+                edgeColoring = &edgeColoringSimple;
+            else if (!strcmp(argv[argPos+1], "inktrap"))
+                edgeColoring = &edgeColoringInkTrap;
+            else if (!strcmp(argv[argPos+1], "distance"))
+                edgeColoring = &edgeColoringByDistance;
             else
                 fputs("Unknown coloring strategy specified.\n", stderr);
             argPos += 2;
@@ -1164,12 +1167,12 @@ int main(int argc, const char *const *argv) {
                 generateSDF(sdf, shape, projection, range, generatorConfig);
             break;
         }
-        case PSEUDO: {
+        case PERPENDICULAR: {
             sdf = Bitmap<float, 1>(width, height);
             if (legacyMode)
-                generatePseudoSDF_legacy(sdf, shape, range, scale, translate);
+                generatePSDF_legacy(sdf, shape, range, scale, translate);
             else
-                generatePseudoSDF(sdf, shape, projection, range, generatorConfig);
+                generatePSDF(sdf, shape, projection, range, generatorConfig);
             break;
         }
         case MULTI: {
@@ -1208,7 +1211,7 @@ int main(int argc, const char *const *argv) {
     if (orientation == REVERSE) {
         switch (mode) {
             case SINGLE:
-            case PSEUDO:
+            case PERPENDICULAR:
                 invertColor<1>(sdf);
                 break;
             case MULTI:
@@ -1223,7 +1226,7 @@ int main(int argc, const char *const *argv) {
     if (scanlinePass) {
         switch (mode) {
             case SINGLE:
-            case PSEUDO:
+            case PERPENDICULAR:
                 distanceSignCorrection(sdf, shape, projection, fillRule);
                 break;
             case MULTI:
@@ -1241,7 +1244,7 @@ int main(int argc, const char *const *argv) {
         float *pixel = NULL, *pixelsEnd = NULL;
         switch (mode) {
             case SINGLE:
-            case PSEUDO:
+            case PERPENDICULAR:
                 pixel = (float *) sdf;
                 pixelsEnd = pixel+1*sdf.width()*sdf.height();
                 break;
@@ -1271,7 +1274,7 @@ int main(int argc, const char *const *argv) {
     const char *error = NULL;
     switch (mode) {
         case SINGLE:
-        case PSEUDO:
+        case PERPENDICULAR:
             if ((error = writeOutput<1>(sdf, output, format))) {
                 fprintf(stderr, "%s\n", error);
                 return 1;

+ 6 - 2
msdfgen.h

@@ -40,8 +40,8 @@ namespace msdfgen {
 /// Generates a conventional single-channel signed distance field.
 void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config = GeneratorConfig());
 
-/// Generates a single-channel signed pseudo-distance field.
-void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config = GeneratorConfig());
+/// Generates a single-channel signed perpendicular distance field.
+void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config = GeneratorConfig());
 
 /// Generates a multi-channel signed distance field. Edge colors must be assigned first! (See edgeColoringSimple)
 void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, const Projection &projection, double range, const MSDFGeneratorConfig &config = MSDFGeneratorConfig());
@@ -50,13 +50,17 @@ void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, const P
 void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, const Projection &projection, double range, const MSDFGeneratorConfig &config = MSDFGeneratorConfig());
 
 // Old version of the function API's kept for backwards compatibility
+void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, const Projection &projection, double range, const GeneratorConfig &config = GeneratorConfig());
+
 void generateSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport = true);
+void generatePSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport = true);
 void generatePseudoSDF(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, bool overlapSupport = true);
 void generateMSDF(const BitmapRef<float, 3> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, const ErrorCorrectionConfig &errorCorrectionConfig = ErrorCorrectionConfig(), bool overlapSupport = true);
 void generateMTSDF(const BitmapRef<float, 4> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, const ErrorCorrectionConfig &errorCorrectionConfig = ErrorCorrectionConfig(), bool overlapSupport = true);
 
 // Original simpler versions of the previous functions, which work well under normal circumstances, but cannot deal with overlapping contours.
 void generateSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate);
+void generatePSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate);
 void generatePseudoSDF_legacy(const BitmapRef<float, 1> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate);
 void generateMSDF_legacy(const BitmapRef<float, 3> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, ErrorCorrectionConfig errorCorrectionConfig = ErrorCorrectionConfig());
 void generateMTSDF_legacy(const BitmapRef<float, 4> &output, const Shape &shape, double range, const Vector2 &scale, const Vector2 &translate, ErrorCorrectionConfig errorCorrectionConfig = ErrorCorrectionConfig());