initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
261
thirdparty/msdfgen/core/edge-selectors.cpp
vendored
Normal file
261
thirdparty/msdfgen/core/edge-selectors.cpp
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
|
||||
#include "edge-selectors.h"
|
||||
|
||||
#include "arithmetics.hpp"
|
||||
|
||||
namespace msdfgen {
|
||||
|
||||
#define DISTANCE_DELTA_FACTOR 1.001
|
||||
|
||||
TrueDistanceSelector::EdgeCache::EdgeCache() : absDistance(0) { }
|
||||
|
||||
void TrueDistanceSelector::reset(const Point2 &p) {
|
||||
double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();
|
||||
minDistance.distance += nonZeroSign(minDistance.distance)*delta;
|
||||
this->p = p;
|
||||
}
|
||||
|
||||
void TrueDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
|
||||
double delta = DISTANCE_DELTA_FACTOR*(p-cache.point).length();
|
||||
if (cache.absDistance-delta <= fabs(minDistance.distance)) {
|
||||
double dummy;
|
||||
SignedDistance distance = edge->signedDistance(p, dummy);
|
||||
if (distance < minDistance)
|
||||
minDistance = distance;
|
||||
cache.point = p;
|
||||
cache.absDistance = fabs(distance.distance);
|
||||
}
|
||||
}
|
||||
|
||||
void TrueDistanceSelector::merge(const TrueDistanceSelector &other) {
|
||||
if (other.minDistance < minDistance)
|
||||
minDistance = other.minDistance;
|
||||
}
|
||||
|
||||
TrueDistanceSelector::DistanceType TrueDistanceSelector::distance() const {
|
||||
return minDistance.distance;
|
||||
}
|
||||
|
||||
PerpendicularDistanceSelectorBase::EdgeCache::EdgeCache() : absDistance(0), aDomainDistance(0), bDomainDistance(0), aPerpendicularDistance(0), bPerpendicularDistance(0) { }
|
||||
|
||||
bool PerpendicularDistanceSelectorBase::getPerpendicularDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir) {
|
||||
double ts = dotProduct(ep, edgeDir);
|
||||
if (ts > 0) {
|
||||
double perpendicularDistance = crossProduct(ep, edgeDir);
|
||||
if (fabs(perpendicularDistance) < fabs(distance)) {
|
||||
distance = perpendicularDistance;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PerpendicularDistanceSelectorBase::PerpendicularDistanceSelectorBase() : minNegativePerpendicularDistance(-fabs(minTrueDistance.distance)), minPositivePerpendicularDistance(fabs(minTrueDistance.distance)), nearEdge(NULL), nearEdgeParam(0) { }
|
||||
|
||||
void PerpendicularDistanceSelectorBase::reset(double delta) {
|
||||
minTrueDistance.distance += nonZeroSign(minTrueDistance.distance)*delta;
|
||||
minNegativePerpendicularDistance = -fabs(minTrueDistance.distance);
|
||||
minPositivePerpendicularDistance = fabs(minTrueDistance.distance);
|
||||
nearEdge = NULL;
|
||||
nearEdgeParam = 0;
|
||||
}
|
||||
|
||||
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.aPerpendicularDistance < 0 ?
|
||||
cache.aPerpendicularDistance+delta >= minNegativePerpendicularDistance :
|
||||
cache.aPerpendicularDistance-delta <= minPositivePerpendicularDistance
|
||||
)) ||
|
||||
(cache.bDomainDistance > 0 && (cache.bPerpendicularDistance < 0 ?
|
||||
cache.bPerpendicularDistance+delta >= minNegativePerpendicularDistance :
|
||||
cache.bPerpendicularDistance-delta <= minPositivePerpendicularDistance
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
void PerpendicularDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param) {
|
||||
if (distance < minTrueDistance) {
|
||||
minTrueDistance = distance;
|
||||
nearEdge = edge;
|
||||
nearEdgeParam = param;
|
||||
}
|
||||
}
|
||||
|
||||
void PerpendicularDistanceSelectorBase::addEdgePerpendicularDistance(double distance) {
|
||||
if (distance <= 0 && distance > minNegativePerpendicularDistance)
|
||||
minNegativePerpendicularDistance = distance;
|
||||
if (distance >= 0 && distance < minPositivePerpendicularDistance)
|
||||
minPositivePerpendicularDistance = distance;
|
||||
}
|
||||
|
||||
void PerpendicularDistanceSelectorBase::merge(const PerpendicularDistanceSelectorBase &other) {
|
||||
if (other.minTrueDistance < minTrueDistance) {
|
||||
minTrueDistance = other.minTrueDistance;
|
||||
nearEdge = other.nearEdge;
|
||||
nearEdgeParam = other.nearEdgeParam;
|
||||
}
|
||||
if (other.minNegativePerpendicularDistance > minNegativePerpendicularDistance)
|
||||
minNegativePerpendicularDistance = other.minNegativePerpendicularDistance;
|
||||
if (other.minPositivePerpendicularDistance < minPositivePerpendicularDistance)
|
||||
minPositivePerpendicularDistance = other.minPositivePerpendicularDistance;
|
||||
}
|
||||
|
||||
double PerpendicularDistanceSelectorBase::computeDistance(const Point2 &p) const {
|
||||
double minDistance = minTrueDistance.distance < 0 ? minNegativePerpendicularDistance : minPositivePerpendicularDistance;
|
||||
if (nearEdge) {
|
||||
SignedDistance distance = minTrueDistance;
|
||||
nearEdge->distanceToPerpendicularDistance(distance, p, nearEdgeParam);
|
||||
if (fabs(distance.distance) < fabs(minDistance))
|
||||
minDistance = distance.distance;
|
||||
}
|
||||
return minDistance;
|
||||
}
|
||||
|
||||
SignedDistance PerpendicularDistanceSelectorBase::trueDistance() const {
|
||||
return minTrueDistance;
|
||||
}
|
||||
|
||||
void PerpendicularDistanceSelector::reset(const Point2 &p) {
|
||||
double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();
|
||||
PerpendicularDistanceSelectorBase::reset(delta);
|
||||
this->p = p;
|
||||
}
|
||||
|
||||
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);
|
||||
addEdgeTrueDistance(edge, distance, param);
|
||||
cache.point = p;
|
||||
cache.absDistance = fabs(distance.distance);
|
||||
|
||||
Vector2 ap = p-edge->point(0);
|
||||
Vector2 bp = p-edge->point(1);
|
||||
Vector2 aDir = edge->direction(0).normalize(true);
|
||||
Vector2 bDir = edge->direction(1).normalize(true);
|
||||
Vector2 prevDir = prevEdge->direction(1).normalize(true);
|
||||
Vector2 nextDir = nextEdge->direction(0).normalize(true);
|
||||
double add = dotProduct(ap, (prevDir+aDir).normalize(true));
|
||||
double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));
|
||||
if (add > 0) {
|
||||
double pd = distance.distance;
|
||||
if (getPerpendicularDistance(pd, ap, -aDir))
|
||||
addEdgePerpendicularDistance(pd = -pd);
|
||||
cache.aPerpendicularDistance = pd;
|
||||
}
|
||||
if (bdd > 0) {
|
||||
double pd = distance.distance;
|
||||
if (getPerpendicularDistance(pd, bp, bDir))
|
||||
addEdgePerpendicularDistance(pd);
|
||||
cache.bPerpendicularDistance = pd;
|
||||
}
|
||||
cache.aDomainDistance = add;
|
||||
cache.bDomainDistance = bdd;
|
||||
}
|
||||
}
|
||||
|
||||
PerpendicularDistanceSelector::DistanceType PerpendicularDistanceSelector::distance() const {
|
||||
return computeDistance(p);
|
||||
}
|
||||
|
||||
void MultiDistanceSelector::reset(const Point2 &p) {
|
||||
double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();
|
||||
r.reset(delta);
|
||||
g.reset(delta);
|
||||
b.reset(delta);
|
||||
this->p = p;
|
||||
}
|
||||
|
||||
void MultiDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
|
||||
if (
|
||||
(edge->color&RED && r.isEdgeRelevant(cache, edge, p)) ||
|
||||
(edge->color&GREEN && g.isEdgeRelevant(cache, edge, p)) ||
|
||||
(edge->color&BLUE && b.isEdgeRelevant(cache, edge, p))
|
||||
) {
|
||||
double param;
|
||||
SignedDistance distance = edge->signedDistance(p, param);
|
||||
if (edge->color&RED)
|
||||
r.addEdgeTrueDistance(edge, distance, param);
|
||||
if (edge->color&GREEN)
|
||||
g.addEdgeTrueDistance(edge, distance, param);
|
||||
if (edge->color&BLUE)
|
||||
b.addEdgeTrueDistance(edge, distance, param);
|
||||
cache.point = p;
|
||||
cache.absDistance = fabs(distance.distance);
|
||||
|
||||
Vector2 ap = p-edge->point(0);
|
||||
Vector2 bp = p-edge->point(1);
|
||||
Vector2 aDir = edge->direction(0).normalize(true);
|
||||
Vector2 bDir = edge->direction(1).normalize(true);
|
||||
Vector2 prevDir = prevEdge->direction(1).normalize(true);
|
||||
Vector2 nextDir = nextEdge->direction(0).normalize(true);
|
||||
double add = dotProduct(ap, (prevDir+aDir).normalize(true));
|
||||
double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));
|
||||
if (add > 0) {
|
||||
double pd = distance.distance;
|
||||
if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, ap, -aDir)) {
|
||||
pd = -pd;
|
||||
if (edge->color&RED)
|
||||
r.addEdgePerpendicularDistance(pd);
|
||||
if (edge->color&GREEN)
|
||||
g.addEdgePerpendicularDistance(pd);
|
||||
if (edge->color&BLUE)
|
||||
b.addEdgePerpendicularDistance(pd);
|
||||
}
|
||||
cache.aPerpendicularDistance = pd;
|
||||
}
|
||||
if (bdd > 0) {
|
||||
double pd = distance.distance;
|
||||
if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, bp, bDir)) {
|
||||
if (edge->color&RED)
|
||||
r.addEdgePerpendicularDistance(pd);
|
||||
if (edge->color&GREEN)
|
||||
g.addEdgePerpendicularDistance(pd);
|
||||
if (edge->color&BLUE)
|
||||
b.addEdgePerpendicularDistance(pd);
|
||||
}
|
||||
cache.bPerpendicularDistance = pd;
|
||||
}
|
||||
cache.aDomainDistance = add;
|
||||
cache.bDomainDistance = bdd;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiDistanceSelector::merge(const MultiDistanceSelector &other) {
|
||||
r.merge(other.r);
|
||||
g.merge(other.g);
|
||||
b.merge(other.b);
|
||||
}
|
||||
|
||||
MultiDistanceSelector::DistanceType MultiDistanceSelector::distance() const {
|
||||
MultiDistance multiDistance;
|
||||
multiDistance.r = r.computeDistance(p);
|
||||
multiDistance.g = g.computeDistance(p);
|
||||
multiDistance.b = b.computeDistance(p);
|
||||
return multiDistance;
|
||||
}
|
||||
|
||||
SignedDistance MultiDistanceSelector::trueDistance() const {
|
||||
SignedDistance distance = r.trueDistance();
|
||||
if (g.trueDistance() < distance)
|
||||
distance = g.trueDistance();
|
||||
if (b.trueDistance() < distance)
|
||||
distance = b.trueDistance();
|
||||
return distance;
|
||||
}
|
||||
|
||||
MultiAndTrueDistanceSelector::DistanceType MultiAndTrueDistanceSelector::distance() const {
|
||||
MultiDistance multiDistance = MultiDistanceSelector::distance();
|
||||
MultiAndTrueDistance mtd;
|
||||
mtd.r = multiDistance.r;
|
||||
mtd.g = multiDistance.g;
|
||||
mtd.b = multiDistance.b;
|
||||
mtd.a = trueDistance().distance;
|
||||
return mtd;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user