contour-combiners.cpp 5.0 KB

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