edge-selectors.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "edge-selectors.h"
  2. namespace msdfgen {
  3. TrueDistanceSelector::TrueDistanceSelector(const Point2 &p) : p(p) { }
  4. void TrueDistanceSelector::addEdge(const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
  5. double dummy;
  6. SignedDistance distance = edge->signedDistance(p, dummy);
  7. if (distance < minDistance)
  8. minDistance = distance;
  9. }
  10. void TrueDistanceSelector::merge(const TrueDistanceSelector &other) {
  11. if (other.minDistance < minDistance)
  12. minDistance = other.minDistance;
  13. }
  14. TrueDistanceSelector::DistanceType TrueDistanceSelector::distance() const {
  15. return minDistance.distance;
  16. }
  17. bool PseudoDistanceSelectorBase::pointFacingEdge(const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge, const Point2 &p, double param) {
  18. if (param < 0) {
  19. Vector2 prevEdgeDir = -prevEdge->direction(1).normalize(true);
  20. Vector2 edgeDir = edge->direction(0).normalize(true);
  21. Vector2 pointDir = p-edge->point(0);
  22. return dotProduct(pointDir, edgeDir) >= dotProduct(pointDir, prevEdgeDir);
  23. }
  24. if (param > 1) {
  25. Vector2 edgeDir = -edge->direction(1).normalize(true);
  26. Vector2 nextEdgeDir = nextEdge->direction(0).normalize(true);
  27. Vector2 pointDir = p-edge->point(1);
  28. return dotProduct(pointDir, edgeDir) >= dotProduct(pointDir, nextEdgeDir);
  29. }
  30. return true;
  31. }
  32. PseudoDistanceSelectorBase::PseudoDistanceSelectorBase() : nearEdge(NULL), nearEdgeParam(0) { }
  33. void PseudoDistanceSelectorBase::addEdgeTrueDistance(const EdgeSegment *edge, const SignedDistance &distance, double param) {
  34. if (distance < minTrueDistance) {
  35. minTrueDistance = distance;
  36. nearEdge = edge;
  37. nearEdgeParam = param;
  38. }
  39. }
  40. void PseudoDistanceSelectorBase::addEdgePseudoDistance(const SignedDistance &distance) {
  41. SignedDistance &minPseudoDistance = distance.distance < 0 ? minNegativePseudoDistance : minPositivePseudoDistance;
  42. if (distance < minPseudoDistance)
  43. minPseudoDistance = distance;
  44. }
  45. void PseudoDistanceSelectorBase::merge(const PseudoDistanceSelectorBase &other) {
  46. if (other.minTrueDistance < minTrueDistance) {
  47. minTrueDistance = other.minTrueDistance;
  48. nearEdge = other.nearEdge;
  49. nearEdgeParam = other.nearEdgeParam;
  50. }
  51. if (other.minNegativePseudoDistance < minNegativePseudoDistance)
  52. minNegativePseudoDistance = other.minNegativePseudoDistance;
  53. if (other.minPositivePseudoDistance < minPositivePseudoDistance)
  54. minPositivePseudoDistance = other.minPositivePseudoDistance;
  55. }
  56. double PseudoDistanceSelectorBase::computeDistance(const Point2 &p) const {
  57. double minDistance = minTrueDistance.distance < 0 ? minNegativePseudoDistance.distance : minPositivePseudoDistance.distance;
  58. if (nearEdge) {
  59. SignedDistance distance = minTrueDistance;
  60. nearEdge->distanceToPseudoDistance(distance, p, nearEdgeParam);
  61. if (fabs(distance.distance) < fabs(minDistance))
  62. minDistance = distance.distance;
  63. }
  64. return minDistance;
  65. }
  66. SignedDistance PseudoDistanceSelectorBase::trueDistance() const {
  67. return minTrueDistance;
  68. }
  69. PseudoDistanceSelector::PseudoDistanceSelector(const Point2 &p) : p(p) { }
  70. void PseudoDistanceSelector::addEdge(const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
  71. double param;
  72. SignedDistance distance = edge->signedDistance(p, param);
  73. addEdgeTrueDistance(edge, distance, param);
  74. if (pointFacingEdge(prevEdge, edge, nextEdge, p, param)) {
  75. edge->distanceToPseudoDistance(distance, p, param);
  76. addEdgePseudoDistance(distance);
  77. }
  78. }
  79. PseudoDistanceSelector::DistanceType PseudoDistanceSelector::distance() const {
  80. return computeDistance(p);
  81. }
  82. MultiDistanceSelector::MultiDistanceSelector(const Point2 &p) : p(p) { }
  83. void MultiDistanceSelector::addEdge(const EdgeSegment *prevEdge, const EdgeSegment *edge, const EdgeSegment *nextEdge) {
  84. double param;
  85. SignedDistance distance = edge->signedDistance(p, param);
  86. if (edge->color&RED)
  87. r.addEdgeTrueDistance(edge, distance, param);
  88. if (edge->color&GREEN)
  89. g.addEdgeTrueDistance(edge, distance, param);
  90. if (edge->color&BLUE)
  91. b.addEdgeTrueDistance(edge, distance, param);
  92. if (PseudoDistanceSelectorBase::pointFacingEdge(prevEdge, edge, nextEdge, p, param)) {
  93. edge->distanceToPseudoDistance(distance, p, param);
  94. if (edge->color&RED)
  95. r.addEdgePseudoDistance(distance);
  96. if (edge->color&GREEN)
  97. g.addEdgePseudoDistance(distance);
  98. if (edge->color&BLUE)
  99. b.addEdgePseudoDistance(distance);
  100. }
  101. }
  102. void MultiDistanceSelector::merge(const MultiDistanceSelector &other) {
  103. r.merge(other.r);
  104. g.merge(other.g);
  105. b.merge(other.b);
  106. }
  107. MultiDistanceSelector::DistanceType MultiDistanceSelector::distance() const {
  108. MultiDistance multiDistance;
  109. multiDistance.r = r.computeDistance(p);
  110. multiDistance.g = g.computeDistance(p);
  111. multiDistance.b = b.computeDistance(p);
  112. return multiDistance;
  113. }
  114. SignedDistance MultiDistanceSelector::trueDistance() const {
  115. SignedDistance distance = r.trueDistance();
  116. if (g.trueDistance() < distance)
  117. distance = g.trueDistance();
  118. if (b.trueDistance() < distance)
  119. distance = b.trueDistance();
  120. return distance;
  121. }
  122. MultiAndTrueDistanceSelector::MultiAndTrueDistanceSelector(const Point2 &p) : MultiDistanceSelector(p) { }
  123. MultiAndTrueDistanceSelector::DistanceType MultiAndTrueDistanceSelector::distance() const {
  124. MultiDistance multiDistance = MultiDistanceSelector::distance();
  125. MultiAndTrueDistance mtd;
  126. mtd.r = multiDistance.r;
  127. mtd.g = multiDistance.g;
  128. mtd.b = multiDistance.b;
  129. mtd.a = trueDistance().distance;
  130. return mtd;
  131. }
  132. }