contour-combiners.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "contour-combiners.h"
  2. #include <cfloat>
  3. #include "arithmetics.hpp"
  4. namespace msdfgen {
  5. static void initDistance(double &distance) {
  6. distance = -DBL_MAX;
  7. }
  8. static void initDistance(MultiDistance &distance) {
  9. distance.r = -DBL_MAX;
  10. distance.g = -DBL_MAX;
  11. distance.b = -DBL_MAX;
  12. }
  13. static void initDistance(MultiAndTrueDistance &distance) {
  14. distance.r = -DBL_MAX;
  15. distance.g = -DBL_MAX;
  16. distance.b = -DBL_MAX;
  17. distance.a = -DBL_MAX;
  18. }
  19. static double resolveDistance(double distance) {
  20. return distance;
  21. }
  22. static double resolveDistance(const MultiDistance &distance) {
  23. return median(distance.r, distance.g, distance.b);
  24. }
  25. template <class EdgeSelector>
  26. SimpleContourCombiner<EdgeSelector>::SimpleContourCombiner(const Shape &shape) { }
  27. template <class EdgeSelector>
  28. void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
  29. shapeEdgeSelector.reset(p);
  30. }
  31. template <class EdgeSelector>
  32. EdgeSelector &SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
  33. return shapeEdgeSelector;
  34. }
  35. template <class EdgeSelector>
  36. typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner<EdgeSelector>::distance() const {
  37. return shapeEdgeSelector.distance();
  38. }
  39. template class SimpleContourCombiner<TrueDistanceSelector>;
  40. template class SimpleContourCombiner<PerpendicularDistanceSelector>;
  41. template class SimpleContourCombiner<MultiDistanceSelector>;
  42. template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
  43. template <class EdgeSelector>
  44. OverlappingContourCombiner<EdgeSelector>::OverlappingContourCombiner(const Shape &shape) {
  45. windings.reserve(shape.contours.size());
  46. for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
  47. windings.push_back(contour->winding());
  48. edgeSelectors.resize(shape.contours.size());
  49. }
  50. template <class EdgeSelector>
  51. void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
  52. this->p = p;
  53. for (typename std::vector<EdgeSelector>::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector)
  54. contourEdgeSelector->reset(p);
  55. }
  56. template <class EdgeSelector>
  57. EdgeSelector &OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
  58. return edgeSelectors[i];
  59. }
  60. template <class EdgeSelector>
  61. typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingContourCombiner<EdgeSelector>::distance() const {
  62. int contourCount = (int) edgeSelectors.size();
  63. EdgeSelector shapeEdgeSelector;
  64. EdgeSelector innerEdgeSelector;
  65. EdgeSelector outerEdgeSelector;
  66. shapeEdgeSelector.reset(p);
  67. innerEdgeSelector.reset(p);
  68. outerEdgeSelector.reset(p);
  69. for (int i = 0; i < contourCount; ++i) {
  70. DistanceType edgeDistance = edgeSelectors[i].distance();
  71. shapeEdgeSelector.merge(edgeSelectors[i]);
  72. if (windings[i] > 0 && resolveDistance(edgeDistance) >= 0)
  73. innerEdgeSelector.merge(edgeSelectors[i]);
  74. if (windings[i] < 0 && resolveDistance(edgeDistance) <= 0)
  75. outerEdgeSelector.merge(edgeSelectors[i]);
  76. }
  77. DistanceType shapeDistance = shapeEdgeSelector.distance();
  78. DistanceType innerDistance = innerEdgeSelector.distance();
  79. DistanceType outerDistance = outerEdgeSelector.distance();
  80. double innerScalarDistance = resolveDistance(innerDistance);
  81. double outerScalarDistance = resolveDistance(outerDistance);
  82. DistanceType distance;
  83. initDistance(distance);
  84. int winding = 0;
  85. if (innerScalarDistance >= 0 && fabs(innerScalarDistance) <= fabs(outerScalarDistance)) {
  86. distance = innerDistance;
  87. winding = 1;
  88. for (int i = 0; i < contourCount; ++i)
  89. if (windings[i] > 0) {
  90. DistanceType contourDistance = edgeSelectors[i].distance();
  91. if (fabs(resolveDistance(contourDistance)) < fabs(outerScalarDistance) && resolveDistance(contourDistance) > resolveDistance(distance))
  92. distance = contourDistance;
  93. }
  94. } else if (outerScalarDistance <= 0 && fabs(outerScalarDistance) < fabs(innerScalarDistance)) {
  95. distance = outerDistance;
  96. winding = -1;
  97. for (int i = 0; i < contourCount; ++i)
  98. if (windings[i] < 0) {
  99. DistanceType contourDistance = edgeSelectors[i].distance();
  100. if (fabs(resolveDistance(contourDistance)) < fabs(innerScalarDistance) && resolveDistance(contourDistance) < resolveDistance(distance))
  101. distance = contourDistance;
  102. }
  103. } else
  104. return shapeDistance;
  105. for (int i = 0; i < contourCount; ++i)
  106. if (windings[i] != winding) {
  107. DistanceType contourDistance = edgeSelectors[i].distance();
  108. if (resolveDistance(contourDistance)*resolveDistance(distance) >= 0 && fabs(resolveDistance(contourDistance)) < fabs(resolveDistance(distance)))
  109. distance = contourDistance;
  110. }
  111. if (resolveDistance(distance) == resolveDistance(shapeDistance))
  112. distance = shapeDistance;
  113. return distance;
  114. }
  115. template class OverlappingContourCombiner<TrueDistanceSelector>;
  116. template class OverlappingContourCombiner<PerpendicularDistanceSelector>;
  117. template class OverlappingContourCombiner<MultiDistanceSelector>;
  118. template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
  119. }