123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #include "contour-combiners.h"
- #include <cfloat>
- #include "arithmetics.hpp"
- namespace msdfgen {
- static void initDistance(double &distance) {
- distance = -DBL_MAX;
- }
- static void initDistance(MultiDistance &distance) {
- distance.r = -DBL_MAX;
- distance.g = -DBL_MAX;
- distance.b = -DBL_MAX;
- }
- static void initDistance(MultiAndTrueDistance &distance) {
- distance.r = -DBL_MAX;
- distance.g = -DBL_MAX;
- distance.b = -DBL_MAX;
- distance.a = -DBL_MAX;
- }
- static double resolveDistance(double distance) {
- return distance;
- }
- static double resolveDistance(const MultiDistance &distance) {
- return median(distance.r, distance.g, distance.b);
- }
- template <class EdgeSelector>
- SimpleContourCombiner<EdgeSelector>::SimpleContourCombiner(const Shape &shape) { }
- template <class EdgeSelector>
- void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
- shapeEdgeSelector.reset(p);
- }
- template <class EdgeSelector>
- EdgeSelector &SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
- return shapeEdgeSelector;
- }
- template <class EdgeSelector>
- typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner<EdgeSelector>::distance() const {
- return shapeEdgeSelector.distance();
- }
- template class SimpleContourCombiner<TrueDistanceSelector>;
- template class SimpleContourCombiner<PerpendicularDistanceSelector>;
- template class SimpleContourCombiner<MultiDistanceSelector>;
- template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
- template <class EdgeSelector>
- OverlappingContourCombiner<EdgeSelector>::OverlappingContourCombiner(const Shape &shape) {
- windings.reserve(shape.contours.size());
- for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
- windings.push_back(contour->winding());
- edgeSelectors.resize(shape.contours.size());
- }
- template <class EdgeSelector>
- void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
- this->p = p;
- for (typename std::vector<EdgeSelector>::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector)
- contourEdgeSelector->reset(p);
- }
- template <class EdgeSelector>
- EdgeSelector &OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
- return edgeSelectors[i];
- }
- template <class EdgeSelector>
- typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingContourCombiner<EdgeSelector>::distance() const {
- int contourCount = (int) edgeSelectors.size();
- EdgeSelector shapeEdgeSelector;
- EdgeSelector innerEdgeSelector;
- EdgeSelector outerEdgeSelector;
- shapeEdgeSelector.reset(p);
- innerEdgeSelector.reset(p);
- outerEdgeSelector.reset(p);
- for (int i = 0; i < contourCount; ++i) {
- DistanceType edgeDistance = edgeSelectors[i].distance();
- shapeEdgeSelector.merge(edgeSelectors[i]);
- if (windings[i] > 0 && resolveDistance(edgeDistance) >= 0)
- innerEdgeSelector.merge(edgeSelectors[i]);
- if (windings[i] < 0 && resolveDistance(edgeDistance) <= 0)
- outerEdgeSelector.merge(edgeSelectors[i]);
- }
- DistanceType shapeDistance = shapeEdgeSelector.distance();
- DistanceType innerDistance = innerEdgeSelector.distance();
- DistanceType outerDistance = outerEdgeSelector.distance();
- double innerScalarDistance = resolveDistance(innerDistance);
- double outerScalarDistance = resolveDistance(outerDistance);
- DistanceType distance;
- initDistance(distance);
- int winding = 0;
- if (innerScalarDistance >= 0 && fabs(innerScalarDistance) <= fabs(outerScalarDistance)) {
- distance = innerDistance;
- winding = 1;
- for (int i = 0; i < contourCount; ++i)
- if (windings[i] > 0) {
- DistanceType contourDistance = edgeSelectors[i].distance();
- if (fabs(resolveDistance(contourDistance)) < fabs(outerScalarDistance) && resolveDistance(contourDistance) > resolveDistance(distance))
- distance = contourDistance;
- }
- } else if (outerScalarDistance <= 0 && fabs(outerScalarDistance) < fabs(innerScalarDistance)) {
- distance = outerDistance;
- winding = -1;
- for (int i = 0; i < contourCount; ++i)
- if (windings[i] < 0) {
- DistanceType contourDistance = edgeSelectors[i].distance();
- if (fabs(resolveDistance(contourDistance)) < fabs(innerScalarDistance) && resolveDistance(contourDistance) < resolveDistance(distance))
- distance = contourDistance;
- }
- } else
- return shapeDistance;
- for (int i = 0; i < contourCount; ++i)
- if (windings[i] != winding) {
- DistanceType contourDistance = edgeSelectors[i].distance();
- if (resolveDistance(contourDistance)*resolveDistance(distance) >= 0 && fabs(resolveDistance(contourDistance)) < fabs(resolveDistance(distance)))
- distance = contourDistance;
- }
- if (resolveDistance(distance) == resolveDistance(shapeDistance))
- distance = shapeDistance;
- return distance;
- }
- template class OverlappingContourCombiner<TrueDistanceSelector>;
- template class OverlappingContourCombiner<PerpendicularDistanceSelector>;
- template class OverlappingContourCombiner<MultiDistanceSelector>;
- template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
- }
|