Path: blob/master/thirdparty/msdfgen/core/edge-selectors.cpp
9902 views
1#include "edge-selectors.h"23#include "arithmetics.hpp"45namespace msdfgen {67#define DISTANCE_DELTA_FACTOR 1.00189TrueDistanceSelector::EdgeCache::EdgeCache() : absDistance(0) { }1011void TrueDistanceSelector::reset(const Point2 &p) {12double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();13minDistance.distance += nonZeroSign(minDistance.distance)*delta;14this->p = p;15}1617void TrueDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {18double delta = DISTANCE_DELTA_FACTOR*(p-cache.point).length();19if (cache.absDistance-delta <= fabs(minDistance.distance)) {20double dummy;21SignedDistance distance = edge->signedDistance(p, dummy);22if (distance < minDistance)23minDistance = distance;24cache.point = p;25cache.absDistance = fabs(distance.distance);26}27}2829void TrueDistanceSelector::merge(const TrueDistanceSelector &other) {30if (other.minDistance < minDistance)31minDistance = other.minDistance;32}3334TrueDistanceSelector::DistanceType TrueDistanceSelector::distance() const {35return minDistance.distance;36}3738PerpendicularDistanceSelectorBase::EdgeCache::EdgeCache() : absDistance(0), aDomainDistance(0), bDomainDistance(0), aPerpendicularDistance(0), bPerpendicularDistance(0) { }3940bool PerpendicularDistanceSelectorBase::getPerpendicularDistance(double &distance, const Vector2 &ep, const Vector2 &edgeDir) {41double ts = dotProduct(ep, edgeDir);42if (ts > 0) {43double perpendicularDistance = crossProduct(ep, edgeDir);44if (fabs(perpendicularDistance) < fabs(distance)) {45distance = perpendicularDistance;46return true;47}48}49return false;50}5152PerpendicularDistanceSelectorBase::PerpendicularDistanceSelectorBase() : minNegativePerpendicularDistance(-fabs(minTrueDistance.distance)), minPositivePerpendicularDistance(fabs(minTrueDistance.distance)), nearEdge(NULL), nearEdgeParam(0) { }5354void PerpendicularDistanceSelectorBase::reset(double delta) {55minTrueDistance.distance += nonZeroSign(minTrueDistance.distance)*delta;56minNegativePerpendicularDistance = -fabs(minTrueDistance.distance);57minPositivePerpendicularDistance = fabs(minTrueDistance.distance);58nearEdge = NULL;59nearEdgeParam = 0;60}6162bool PerpendicularDistanceSelectorBase::isEdgeRelevant(const EdgeCache &cache, const EdgeSegment *edge, const Point2 &p) const {63double delta = DISTANCE_DELTA_FACTOR*(p-cache.point).length();64return (65cache.absDistance-delta <= fabs(minTrueDistance.distance) ||66fabs(cache.aDomainDistance) < delta ||67fabs(cache.bDomainDistance) < delta ||68(cache.aDomainDistance > 0 && (cache.aPerpendicularDistance < 0 ?69cache.aPerpendicularDistance+delta >= minNegativePerpendicularDistance :70cache.aPerpendicularDistance-delta <= minPositivePerpendicularDistance71)) ||72(cache.bDomainDistance > 0 && (cache.bPerpendicularDistance < 0 ?73cache.bPerpendicularDistance+delta >= minNegativePerpendicularDistance :74cache.bPerpendicularDistance-delta <= minPositivePerpendicularDistance75))76);77}7879void PerpendicularDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param) {80if (distance < minTrueDistance) {81minTrueDistance = distance;82nearEdge = edge;83nearEdgeParam = param;84}85}8687void PerpendicularDistanceSelectorBase::addEdgePerpendicularDistance(double distance) {88if (distance <= 0 && distance > minNegativePerpendicularDistance)89minNegativePerpendicularDistance = distance;90if (distance >= 0 && distance < minPositivePerpendicularDistance)91minPositivePerpendicularDistance = distance;92}9394void PerpendicularDistanceSelectorBase::merge(const PerpendicularDistanceSelectorBase &other) {95if (other.minTrueDistance < minTrueDistance) {96minTrueDistance = other.minTrueDistance;97nearEdge = other.nearEdge;98nearEdgeParam = other.nearEdgeParam;99}100if (other.minNegativePerpendicularDistance > minNegativePerpendicularDistance)101minNegativePerpendicularDistance = other.minNegativePerpendicularDistance;102if (other.minPositivePerpendicularDistance < minPositivePerpendicularDistance)103minPositivePerpendicularDistance = other.minPositivePerpendicularDistance;104}105106double PerpendicularDistanceSelectorBase::computeDistance(const Point2 &p) const {107double minDistance = minTrueDistance.distance < 0 ? minNegativePerpendicularDistance : minPositivePerpendicularDistance;108if (nearEdge) {109SignedDistance distance = minTrueDistance;110nearEdge->distanceToPerpendicularDistance(distance, p, nearEdgeParam);111if (fabs(distance.distance) < fabs(minDistance))112minDistance = distance.distance;113}114return minDistance;115}116117SignedDistance PerpendicularDistanceSelectorBase::trueDistance() const {118return minTrueDistance;119}120121void PerpendicularDistanceSelector::reset(const Point2 &p) {122double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();123PerpendicularDistanceSelectorBase::reset(delta);124this->p = p;125}126127void PerpendicularDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {128if (isEdgeRelevant(cache, edge, p)) {129double param;130SignedDistance distance = edge->signedDistance(p, param);131addEdgeTrueDistance(edge, distance, param);132cache.point = p;133cache.absDistance = fabs(distance.distance);134135Vector2 ap = p-edge->point(0);136Vector2 bp = p-edge->point(1);137Vector2 aDir = edge->direction(0).normalize(true);138Vector2 bDir = edge->direction(1).normalize(true);139Vector2 prevDir = prevEdge->direction(1).normalize(true);140Vector2 nextDir = nextEdge->direction(0).normalize(true);141double add = dotProduct(ap, (prevDir+aDir).normalize(true));142double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));143if (add > 0) {144double pd = distance.distance;145if (getPerpendicularDistance(pd, ap, -aDir))146addEdgePerpendicularDistance(pd = -pd);147cache.aPerpendicularDistance = pd;148}149if (bdd > 0) {150double pd = distance.distance;151if (getPerpendicularDistance(pd, bp, bDir))152addEdgePerpendicularDistance(pd);153cache.bPerpendicularDistance = pd;154}155cache.aDomainDistance = add;156cache.bDomainDistance = bdd;157}158}159160PerpendicularDistanceSelector::DistanceType PerpendicularDistanceSelector::distance() const {161return computeDistance(p);162}163164void MultiDistanceSelector::reset(const Point2 &p) {165double delta = DISTANCE_DELTA_FACTOR*(p-this->p).length();166r.reset(delta);167g.reset(delta);168b.reset(delta);169this->p = p;170}171172void MultiDistanceSelector::addEdge(EdgeCache &cache, const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {173if (174(edge->color&RED && r.isEdgeRelevant(cache, edge, p)) ||175(edge->color&GREEN && g.isEdgeRelevant(cache, edge, p)) ||176(edge->color&BLUE && b.isEdgeRelevant(cache, edge, p))177) {178double param;179SignedDistance distance = edge->signedDistance(p, param);180if (edge->color&RED)181r.addEdgeTrueDistance(edge, distance, param);182if (edge->color&GREEN)183g.addEdgeTrueDistance(edge, distance, param);184if (edge->color&BLUE)185b.addEdgeTrueDistance(edge, distance, param);186cache.point = p;187cache.absDistance = fabs(distance.distance);188189Vector2 ap = p-edge->point(0);190Vector2 bp = p-edge->point(1);191Vector2 aDir = edge->direction(0).normalize(true);192Vector2 bDir = edge->direction(1).normalize(true);193Vector2 prevDir = prevEdge->direction(1).normalize(true);194Vector2 nextDir = nextEdge->direction(0).normalize(true);195double add = dotProduct(ap, (prevDir+aDir).normalize(true));196double bdd = -dotProduct(bp, (bDir+nextDir).normalize(true));197if (add > 0) {198double pd = distance.distance;199if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, ap, -aDir)) {200pd = -pd;201if (edge->color&RED)202r.addEdgePerpendicularDistance(pd);203if (edge->color&GREEN)204g.addEdgePerpendicularDistance(pd);205if (edge->color&BLUE)206b.addEdgePerpendicularDistance(pd);207}208cache.aPerpendicularDistance = pd;209}210if (bdd > 0) {211double pd = distance.distance;212if (PerpendicularDistanceSelectorBase::getPerpendicularDistance(pd, bp, bDir)) {213if (edge->color&RED)214r.addEdgePerpendicularDistance(pd);215if (edge->color&GREEN)216g.addEdgePerpendicularDistance(pd);217if (edge->color&BLUE)218b.addEdgePerpendicularDistance(pd);219}220cache.bPerpendicularDistance = pd;221}222cache.aDomainDistance = add;223cache.bDomainDistance = bdd;224}225}226227void MultiDistanceSelector::merge(const MultiDistanceSelector &other) {228r.merge(other.r);229g.merge(other.g);230b.merge(other.b);231}232233MultiDistanceSelector::DistanceType MultiDistanceSelector::distance() const {234MultiDistance multiDistance;235multiDistance.r = r.computeDistance(p);236multiDistance.g = g.computeDistance(p);237multiDistance.b = b.computeDistance(p);238return multiDistance;239}240241SignedDistance MultiDistanceSelector::trueDistance() const {242SignedDistance distance = r.trueDistance();243if (g.trueDistance() < distance)244distance = g.trueDistance();245if (b.trueDistance() < distance)246distance = b.trueDistance();247return distance;248}249250MultiAndTrueDistanceSelector::DistanceType MultiAndTrueDistanceSelector::distance() const {251MultiDistance multiDistance = MultiDistanceSelector::distance();252MultiAndTrueDistance mtd;253mtd.r = multiDistance.r;254mtd.g = multiDistance.g;255mtd.b = multiDistance.b;256mtd.a = trueDistance().distance;257return mtd;258}259260}261262263