2
0

contour-combiners.cpp 5.2 KB

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