36 #ifndef VIGRA_POLYGON_HXX 
   37 #define VIGRA_POLYGON_HXX 
   45 #include "tinyvector.hxx" 
   46 #include "array_vector.hxx" 
   47 #include "gaussians.hxx" 
   48 #include "splines.hxx" 
   49 #include "linear_solve.hxx" 
   55 template < 
class Po
int >    
 
   56 bool pointYXOrdering(Point 
const & p1, Point 
const & p2) 
 
   58     return (p1[1]<p2[1]) || (p1[1] == p2[1] && p1[0] < p2[0]);
 
   61 template < 
class Po
int >    
 
   62 bool orderedClockwise(
const Point &O, 
const Point &A, 
const Point &B)
 
   64     return (A[0] - O[0]) * (B[1] - O[1]) - (A[1] - O[1]) * (B[0] - O[0]) <= 0;
 
   77 template<
class POINT=TinyVector<
double, 2> >
 
   85     typedef typename Base::value_type             value_type;
 
   86     typedef typename Base::reference              reference;
 
   87     typedef typename Base::const_reference        const_reference;
 
   88     typedef typename Base::pointer                pointer;
 
   89     typedef typename Base::const_pointer          const_pointer;
 
   90     typedef typename Base::iterator               iterator;
 
   91     typedef typename Base::const_iterator         const_iterator;
 
   92     typedef typename Base::reverse_iterator       reverse_iterator;
 
   93     typedef typename Base::const_reverse_iterator const_reverse_iterator;
 
   94     typedef typename Base::size_type              size_type;
 
   95     typedef typename Base::difference_type        difference_type;
 
   96     typedef typename POINT::value_type            coordinate_type;
 
  115       partialAreaValid_(
false)
 
  121       partialAreaValid_(
false)
 
  124     template <
class InputIterator>
 
  125     Polygon(InputIterator b, InputIterator e)
 
  128       partialAreaValid_(
false)
 
  133         invalidateProperties();
 
  137     void invalidateProperties()
 
  139         lengthValid_ = 
false;
 
  140         partialAreaValid_ = 
false;
 
  143     double length()
 const 
  148             for(
unsigned int i = 1; i < 
size(); ++i)
 
  149                 length_ += ((*
this)[i] - (*this)[i-1]).magnitude();
 
  155     double partialArea()
 const 
  157         if(!partialAreaValid_)
 
  160             for(
unsigned int i = 1; i < 
size(); ++i)
 
  161                 partialArea_ += ((*
this)[i][0]*(*this)[i-1][1] -
 
  162                                  (*this)[i][1]*(*this)[i-1][0]);
 
  164             partialAreaValid_ = 
true;
 
  171         vigra_precondition(
closed(),
 
  172                            "Polygon::area() requires polygon to be closed!");
 
  173         return abs(partialArea());
 
  179         return size() <= 1 || back() == front();
 
  189         if(index < 
size() - 1)
 
  190             return (1.0 - offset) * (*this)[index] + offset * (*this)[index+1];
 
  192             return (*
this)[index];
 
  204     bool contains(const_reference point, coordinate_type tolerance) 
const;
 
  206     bool contains(const_reference point)
 const 
  208         return contains(point, 2.0*NumericTraits<coordinate_type>::epsilon());
 
  211     void push_back(const_reference v)
 
  216                 length_ += (v - back()).magnitude();
 
  217             if(partialAreaValid_)
 
  218                 partialArea_ += 0.5*(v[0]*back()[1] - v[1]*back()[0]);
 
  223     void push_back_unsafe(const_reference v)
 
  228     void extend(
const Polygon &other)
 
  233         const_iterator otherBegin(other.begin());
 
  244                     length_ += (other.front() - 
Base::back()).magnitude();
 
  245                 if(partialAreaValid_)
 
  246                     partialArea_ += (other.front()[0]*
Base::back()[1] -
 
  251             length_ += other.length();
 
  252         if(partialAreaValid_)
 
  253             partialArea_ += other.partialArea();
 
  254         Base::insert(
Base::end(), otherBegin, other.end());
 
  257     void setPoint(
unsigned int pos, const_reference x)
 
  259         invalidateProperties();
 
  264     void setPointUnsafe(
unsigned int pos, const_reference x)
 
  277     const_reference operator[](
unsigned int pos)
 const 
  282     const_reference front()
 const 
  287     const_reference back()
 const 
  294         invalidateProperties();
 
  300         invalidateProperties();
 
  304     reverse_iterator rbegin()
 
  306         invalidateProperties();
 
  310     reverse_iterator rend()
 
  312         invalidateProperties();
 
  316     void erase(iterator pos)
 
  318         invalidateProperties();
 
  322     void erase(iterator pos, iterator end)
 
  324         invalidateProperties();
 
  325         Base::erase(pos, end);
 
  328     iterator insert(iterator pos, const_reference x)
 
  330         invalidateProperties();
 
  331         return Base::insert(pos, x);
 
  334     template <
class InputIterator>
 
  335     iterator insert(iterator pos, InputIterator i, InputIterator end)
 
  337         invalidateProperties();
 
  338         return Base::insert(pos, i, end);
 
  341     Polygon split(
unsigned int pos)
 
  348         else if(pos < 
size())
 
  350             result.insert(result.begin(), begin() + pos, end());
 
  351             erase(begin() + pos, end());
 
  356     template <
class Sequence>
 
  357     void arcLengthList(Sequence & arcLengths)
 const 
  360         arcLengths.push_back(0.0);
 
  361         for(
unsigned int i = 1; i < 
size(); ++i)
 
  363             length += ((*this)[i] - (*this)[i-1]).magnitude();
 
  364             arcLengths.push_back(length);
 
  381         vigra_precondition(this->
size() > 0,
 
  382             "Polygon:.arcLengthQuantile(): polygon is empty.");
 
  383         if(quantile == 0.0 || this->
size() == 1)
 
  386             return this->
size() - 1.0;
 
  387         vigra_precondition(0.0 < quantile && quantile < 1.0,
 
  388             "Polygon:.arcLengthQuantile(): quantile must be between 0 and 1.");
 
  390         arcLength.reserve(this->
size());
 
  391         arcLengthList(arcLength);
 
  392         double length = quantile*arcLength.
back();
 
  394         for(; k<this->
size(); ++k)
 
  395             if(arcLength[k] >= length)
 
  398         return k + (length - arcLength[k]) / (arcLength[k+1] - arcLength[k]);
 
  404         std::swap(length_, rhs.length_);
 
  405         std::swap(lengthValid_, rhs.lengthValid_);
 
  406         std::swap(partialArea_, rhs.partialArea_);
 
  407         std::swap(partialAreaValid_, rhs.partialAreaValid_);
 
  413         if(partialAreaValid_)
 
  414             partialArea_ = -partialArea_;
 
  417     POINT nearestPoint(const_reference p) 
const;
 
  419     Polygon & operator+=(POINT 
const & offset)
 
  422             partialAreaValid_ = 
false;
 
  423         for(
unsigned int i = 0; i < 
size(); ++i)
 
  424             Base::operator[](i) += offset;
 
  428     Polygon & operator-=(POINT 
const & offset)
 
  431             partialAreaValid_ = 
false;
 
  432         for(
unsigned int i = 0; i < 
size(); ++i)
 
  433             Base::operator[](i) -= offset;
 
  437     Polygon & operator*=(
double scale)
 
  439         partialArea_ *= 
sq(scale);
 
  441         for(
unsigned int i = 0; i < 
size(); ++i)
 
  442             Base::operator[](i) *= scale;
 
  446     Polygon & operator/=(
double scale)
 
  448         partialArea_ /= 
sq(scale);
 
  450         for(
unsigned int i = 0; i < 
size(); ++i)
 
  451             Base::operator[](i) /= scale;
 
  455     bool operator==(Polygon 
const & rhs)
 const 
  457         if(
size() != rhs.size())
 
  459         for(size_type k=0; k<
size(); ++k)
 
  460             if((*
this)[k] != rhs[k])
 
  465     bool operator!=(Polygon 
const & rhs)
 const 
  467         return !((*this) == rhs);
 
  472     mutable double length_;
 
  473     mutable bool lengthValid_;
 
  474     mutable double partialArea_;
 
  475     mutable bool partialAreaValid_;
 
  478 template <
class POINT>
 
  479 POINT Polygon<POINT>::nearestPoint(const_reference p)
 const 
  481     double dist = NumericTraits<double>::max();
 
  483     for(
unsigned int k=1; k<size(); ++k)
 
  485         POINT dp = (*this)[k] - (*this)[k-1];
 
  486         POINT dc = p - (*this)[k-1];
 
  487         double t = 
dot(dp, dc);
 
  492             double d = 
norm((*
this)[k]-p);
 
  501             double d = 
norm((*
this)[k-1]-p);
 
  510             POINT pp = (*this)[k-1] + t*dp;
 
  511             double d = 
norm(pp-p);
 
  522 template <
class POINT>
 
  525                          coordinate_type tolerance)
 const 
  528     vigra_precondition(closed(),
 
  529                        "Polygon::contains() requires polygon to be closed!");
 
  537     for(
int k=0; k<n; ++k)
 
  539             ((Base&)p)[k][1] = 0.0;
 
  542     bool drop_next_start_point = 
false;
 
  543     int first_point_maybe_dropped = -1;
 
  544     for(
int k=0; k<n-1; ++k)
 
  546         Point 
const & p1 = p[k];
 
  547         Point 
const & p2 = p[k+1];
 
  552         double t = (p2[0] - p1[0]) / (p2[1] - p1[1]);
 
  568         if(drop_next_start_point)
 
  571             drop_next_start_point = 
false;
 
  573         if(first_point_maybe_dropped == -1)
 
  575             if(y == 0.0 && p1[0] - p1[1]*t < 0.0)
 
  576                 first_point_maybe_dropped = 1;
 
  578                 first_point_maybe_dropped = 0;
 
  580         if(y*dy <= 0.0 && yend*dy > 0.0)  
 
  582             double x = p1[0] - p1[1]*t;
 
  588         else if(p2[1] == 0.0) 
 
  591             bool convex = detail::orderedClockwise(p1, p2, p[j]);
 
  594                 double x = p2[0] - p2[1]*t;
 
  600             for(; j != k+1; j = (j+1)%n)
 
  602                 double bend = dy*(p[j][1] - yend);
 
  609                 if((convex && bend > 0.0) || (!convex && bend < 0.0))
 
  610                     drop_next_start_point = 
true;
 
  616     if(drop_next_start_point && first_point_maybe_dropped == 1)
 
  619     return (result % 2) != 0;
 
  622 template <
class POINT>
 
  626     for(
unsigned int i = 0; i < p.
size(); ++i)
 
  628         result.setPointUnsafe(i, 
round(p[i]));
 
  633 template <
class POINT>
 
  634 inline Polygon<TinyVector<std::ptrdiff_t, 2> > 
roundi(Polygon<POINT> 
const & p) 
 
  636     Polygon<TinyVector<std::ptrdiff_t, 2> > result(p.size());
 
  637     for(
unsigned int i = 0; i < p.size(); ++i)
 
  639         result.setPointUnsafe(i,
roundi(p[i]));
 
  644 template <
class POINT>
 
  645 inline Polygon<POINT> 
 
  646 operator+(Polygon<POINT> 
const & p, POINT 
const & offset)
 
  648     return Polygon<POINT>(p) += offset;
 
  651 template <
class POINT>
 
  652 inline Polygon<POINT> 
 
  653 operator+(POINT 
const & offset, Polygon<POINT> 
const & p)
 
  655     return Polygon<POINT>(p) += offset;
 
  658 template <
class POINT>
 
  659 inline Polygon<POINT> 
 
  662     Polygon<POINT> result(p.size());
 
  663     for(
unsigned int i = 0; i < p.size(); ++i)
 
  664         result.setPointUnsafe(i, -p[i]);
 
  668 template <
class POINT>
 
  669 inline Polygon<POINT> 
 
  670 operator-(Polygon<POINT> 
const & p, POINT 
const & offset)
 
  672     return Polygon<POINT>(p) -= offset;
 
  675 template <
class POINT>
 
  676 inline Polygon<POINT> 
 
  677 operator*(Polygon<POINT> 
const & p, 
double scale)
 
  679     return Polygon<POINT>(p) *= scale;
 
  682 template <
class POINT>
 
  683 inline Polygon<POINT> 
 
  684 operator*(
double scale, Polygon<POINT> 
const & p)
 
  686     return Polygon<POINT>(p) *= scale;
 
  690 template <
class POINT>
 
  691 inline Polygon<POINT> 
 
  692 operator/(Polygon<POINT> 
const & p, 
double scale)
 
  694     return Polygon<POINT>(p) /= scale;
 
  697 template <
class POINT>
 
  698 inline Polygon<POINT> 
 
  701     Polygon<POINT> result(p.size());
 
  702     for(
unsigned int i = 0; i < p.size(); ++i)
 
  704         result.setPointUnsafe(i, POINT(p[i][1], p[i][0]));
 
  709 template <
class POINT>
 
  710 inline Polygon<POINT> 
 
  711 reverse(Polygon<POINT> 
const & p)
 
  713     Polygon<POINT> result(p);
 
  718 template<
class Po
int>
 
  719 Point centroid(
const Polygon<Point> &polygon)
 
  721     vigra_precondition(polygon.closed(),
 
  722                        "centroid() expects a closed polygon");
 
  724     TinyVector<double, 2> result;
 
  725     for(
unsigned int i = 1; i < polygon.size(); ++i)
 
  727         double pa = (polygon[i-1][0]*polygon[i][1] -
 
  728                      polygon[i-1][1]*polygon[i][0]);
 
  730         result += (polygon[i-1] + polygon[i])*pa;
 
  732     return result / (3.0*a);
 
  764 template<
class T, 
class S, 
class Po
intArray>
 
  767                Shape2 
const & anchor_point,
 
  768                PointArray & contour_points) 
 
  770     typedef typename PointArray::value_type Point;
 
  772     Shape2 step[4] = { Shape2(0, -1), Shape2(1, 0), Shape2(0, 1), Shape2(-1, 0) };
 
  773     Point contour_offsets[4] = { Point(-0.5, 0), Point(0, -0.5), Point(0.5, 0), Point(0, 0.5) };
 
  775     T foreground = label_image[anchor_point];
 
  780     for(direction = 3; direction >= 0; --direction)
 
  782         position = anchor_point + step[(direction + 1) % 4];
 
  783         if(!label_image.
isInside(position) || label_image[position] != foreground)
 
  787     vigra_precondition(direction >= 0,
 
  788         "extractContour(): the anchor point must be at the region border.");
 
  790     int initial_direction = direction;
 
  791     Shape2 initial_position = position;
 
  796         contour_points.push_back(position + contour_offsets[direction]);
 
  798         Shape2 next_position = position + step[direction];
 
  800         if(label_image.
isInside(next_position) && 
 
  801            label_image[next_position] == foreground)
 
  804             direction = (direction + 1) % 4;
 
  808             position = next_position;
 
  809             int next_direction = (direction + 3) % 4;
 
  810             next_position += step[next_direction];
 
  811             if(!label_image.
isInside(next_position) || 
 
  812                label_image[next_position] != foreground)
 
  815                 direction = next_direction;
 
  816                 position = next_position;
 
  820     while (position != initial_position || direction != initial_direction);
 
  822     contour_points.push_back(contour_points.front()); 
 
  837 template<
class Po
intArray1, 
class Po
intArray2>
 
  838 void convexHull(
const PointArray1 &points, PointArray2 & convex_hull)
 
  840     vigra_precondition(points.size() >= 2,
 
  841                        "convexHull(): at least two input points are needed.");
 
  842     vigra_precondition(points[0].size() == 2,
 
  843                        "convexHull(): 2-dimensional points required.");
 
  845     typedef typename PointArray1::value_type Point;
 
  847     typename PointArray1::const_iterator begin = points.begin();
 
  848     if(points.front() == points.back()) 
 
  851     std::sort(ordered.begin(), ordered.end(), detail::pointYXOrdering<Point>);
 
  855     int n = ordered.
size(), k=0;
 
  858     for (
int i = 0; i < n; i++) 
 
  860         while (k >= 2 && detail::orderedClockwise(H[k-2], H[k-1], ordered[i])) 
 
  865         H.push_back(ordered[i]);
 
  870     for (
int i = n-2, t = k+1; i >= 0; i--) 
 
  872         while (k >= t && detail::orderedClockwise(H[k-2], H[k-1], ordered[i])) 
 
  877         H.push_back(ordered[i]);
 
  881     for(
int i=k-1; i>=0; --i)
 
  882         convex_hull.push_back(H[i]);
 
  899 template<
class Po
int, 
class Array>
 
  900 void createScanIntervals(Polygon<Point> 
const &p, Array & result) 
 
  902     bool drop_next_start_point = 
false;
 
  904     for(
int k=0; k<n-1; ++k)
 
  906         Point 
const & p1 = p[k];
 
  907         Point 
const & p2 = p[k+1];
 
  912         double t = (p2[0] - p1[0]) / (p2[1] - p1[1]);
 
  928         if(drop_next_start_point) 
 
  931             drop_next_start_point = 
false;
 
  933         for(; (y-yend)*dy < 0.0; y += dy)  
 
  935             double x = p1[0] + (y - p1[1])*t;
 
  936             result.push_back(Point(x,y));
 
  941             bool convex = detail::orderedClockwise(p1, p2, p[j]);
 
  944                 result.push_back(p2);
 
  946             for(; j != k+1; j = (j+1)%n)
 
  948                 double bend = dy*(p[j][1] - yend);
 
  955                 if((convex && bend > 0.0) || (!convex && bend < 0.0))
 
  956                     drop_next_start_point = 
true;
 
  962     if(drop_next_start_point)
 
  963         result.erase(result.begin());
 
  965     vigra_invariant((result.size() & 1) == 0,
 
  966         "createScanIntervals(): internal error - should return an even number of points.");
 
  967     sort(result.begin(), result.end(), pointYXOrdering<Point>);
 
  973 template<
class Po
int, 
class FUNCTOR>
 
  975 inspectPolygon(Polygon<Point> 
const &p,
 
  978     vigra_precondition(p.closed(),
 
  979         "inspectPolygon(): polygon must be closed (i.e. first point == last point).");
 
  981     std::vector<Point> scan_intervals;
 
  982     detail::createScanIntervals(p, scan_intervals);
 
  984     for(
unsigned int k=0; k < scan_intervals.size(); k+=2)
 
  989         for(; p[0] < xend; ++p[0])
 
 1004 template<
class Po
int, 
class T, 
class S, 
class Value>
 
 1009     vigra_precondition(p.
closed(),
 
 1010         "fillPolygon(): polygon must be closed (i.e. first point == last point).");
 
 1012     std::vector<Point> scan_intervals;
 
 1013     detail::createScanIntervals(p, scan_intervals);
 
 1015     for(
unsigned int k=0; k < scan_intervals.size(); k+=2)
 
 1020         vigra_invariant(y == scan_intervals[k+1][1],
 
 1021             "fillPolygon(): internal error - scan interval should have same y value.");
 
 1025         if(y >= output_image.
shape(1))
 
 1029         if(xend > output_image.
shape(0))
 
 1030             xend = output_image.
shape(0);
 
 1032         for(; x < xend; ++x)
 
 1033             output_image(x,y) = value;
 
 1043 template<
bool useMaxStep, 
class Po
intIterator, 
class TargetArray>
 
 1044 void simplifyPolygonHelper(
 
 1045     const PointIterator &polyBegin, 
const PointIterator &polyEnd,
 
 1046     TargetArray &simple, 
double epsilon,
 
 1047     double maxStep2 = vigra::NumericTraits<double>::max())
 
 1049     if(polyEnd - polyBegin <= 2)
 
 1052     PointIterator splitPos(polyEnd), lastPoint(polyEnd);
 
 1055     double maxDist = epsilon;
 
 1058     typename TargetArray::value_type
 
 1059         straight(*lastPoint - *polyBegin);
 
 1060     double straightLength2 = straight.squaredMagnitude();
 
 1063     if(straightLength2 > 1e-16)
 
 1065         typename TargetArray::value_type
 
 1066             normal(straight[1], -straight[0]);
 
 1071         PointIterator it(polyBegin);
 
 1072         for(++it; it != lastPoint; ++it)
 
 1074             double dist = fabs(
dot(*it - *polyBegin, normal));
 
 1085         PointIterator it(polyBegin);
 
 1086         for(++it; it != lastPoint; ++it)
 
 1088             double dist = (*it - *polyBegin).magnitude();
 
 1097     if(useMaxStep && (straightLength2 > maxStep2) && (splitPos == polyEnd))
 
 1099         PointIterator it(polyBegin);
 
 1101         double bestD2D = std::fabs((*it - *polyBegin).squaredMagnitude()
 
 1102                                    - (*it - *lastPoint).squaredMagnitude());
 
 1104         for(++it; it != lastPoint; ++it)
 
 1106             double dist2Diff = std::fabs((*it - *polyBegin).squaredMagnitude()
 
 1107                                          - (*it - *lastPoint).squaredMagnitude());
 
 1108             if(dist2Diff < bestD2D)
 
 1110                 bestD2D = dist2Diff;
 
 1116     if(splitPos != polyEnd)
 
 1118         simplifyPolygonHelper<useMaxStep>(
 
 1119             polyBegin, splitPos + 1, simple, epsilon, maxStep2);
 
 1120         simple.push_back(*splitPos);
 
 1121         simplifyPolygonHelper<useMaxStep>(
 
 1122             splitPos, polyEnd, simple, epsilon, maxStep2);
 
 1126 template<
class Po
intArray>
 
 1127 void simplifyPolygon(
 
 1128     const PointArray &poly, PointArray &simple, 
double epsilon)
 
 1130     simple.push_back(poly[0]);
 
 1131     simplifyPolygonHelper<false>(poly.begin(), poly.end(), simple, epsilon);
 
 1132     simple.push_back(poly[poly.size()-1]);
 
 1135 template<
class Po
intArray>
 
 1136 void simplifyPolygon(
 
 1137     const PointArray &poly, PointArray &simple, 
double epsilon, 
double maxStep)
 
 1139     simple.push_back(poly[0]);
 
 1140     simplifyPolygonHelper<true>(poly.begin(), poly.end(),
 
 1141                                 simple, epsilon, maxStep*maxStep);
 
 1142     simple.push_back(poly[poly.size()-1]);
 
 1149 template <
class Po
int>
 
 1150 Point digitalLineIntersection(TinyVector<double, 3> 
const & l1, TinyVector<double, 3> 
const & l2)
 
 1152     double d = l1[0]*l2[1] - l1[1]*l2[0];
 
 1153     return Point((l1[1]*l2[2] - l1[2]*l2[1]) / d, (l1[2]*l2[0] - l1[0]*l2[2]) / d);
 
 1158 template<
class Po
intArray>
 
 1159 void simplifyPolygonDigitalLine(
 
 1160     const PointArray &poly, PointArray &simple, 
int connectivity)
 
 1162     typedef typename PointArray::value_type Point;
 
 1164     int size = poly.size();
 
 1171     vigra_precondition(connectivity == 4 || connectivity == 8,
 
 1172        "simplifyPolygonDigitalLine(): connectivity must be 4 or 8.");
 
 1174     bool isOpenPolygon = poly[size-1] != poly[0];
 
 1176     ArrayVector<TinyVector<double, 3> > lines;
 
 1181     double a = l2[1] - l1[1],
 
 1183            c = -a*l2[0] - b*l2[1];
 
 1184     for(
int k=2; k < size; ++k)
 
 1186         double ab = (connectivity == 4)
 
 1187                         ? std::fabs(a) + std::fabs(b)
 
 1188                         : std::max(std::fabs(a), std::fabs(b));
 
 1189         double d = a*poly[k][0] + b*poly[k][1] + c;
 
 1190         if(d < -1.0 || d > ab)
 
 1193             c = (c - a*r2[0] - b*r2[1]) / 2.0;
 
 1194             lines.push_back(TinyVector<double, 3>(a, b, c));
 
 1202             c = -a*l2[0] - b*l2[1];
 
 1212                 c = -a*l2[0] - b*l2[1];
 
 1215         else if(d >= ab - 1.0)
 
 1223                 c = -a*l2[0] - b*l2[1];
 
 1228     c = (c - a*r2[0] - b*r2[1]) / 2.0;
 
 1229     lines.push_back(TinyVector<double, 3>(a, b, c));
 
 1230     int segments = lines.size();
 
 1233         simple.push_back(poly[0]);
 
 1235         simple.push_back(detail::digitalLineIntersection<Point>(lines[0], lines[segments-1]));
 
 1237     for(
int k=1; k<segments; ++k)
 
 1238         simple.push_back(detail::digitalLineIntersection<Point>(lines[k-1], lines[k]));
 
 1241         simple.push_back(poly[size-1]);
 
 1243         simple.push_back(detail::digitalLineIntersection<Point>(lines[0], lines[segments-1]));
 
 1248 template<
class Po
intArray>
 
 1249 void resamplePolygon(
 
 1250     const PointArray &poly, PointArray &simple, 
double desiredPointDistance)
 
 1252     typedef typename PointArray::value_type Point;
 
 1254     int size = poly.size();
 
 1255     bool isOpenPolygon = !poly.closed();
 
 1257     ArrayVector<double> arcLength;
 
 1258     poly.arcLengthList(arcLength);
 
 1259     int segmentCount = int(
std::ceil(arcLength[size-1] / desiredPointDistance));
 
 1260     if(segmentCount < 2)
 
 1262         simple.push_back(poly[0]);
 
 1266             double dist = (p - poly[0]).magnitude();
 
 1267             for(
int k=2; k < size-1; ++k)
 
 1269                 double d = (poly[k] - poly[0]).magnitude();
 
 1276             simple.push_back(p);
 
 1278         simple.push_back(poly[size-1]);
 
 1282     for(
int k=0; k<size; ++k)
 
 1283         arcLength[k] *= segmentCount / arcLength[size-1];
 
 1285     ArrayVector<Point> integrals(segmentCount+1, Point(0.0, 0.0));
 
 1289     for(
int k=1; k<size; ++k)
 
 1291         double d = arcLength[k];
 
 1292         while(d >= l && l <= segmentCount)
 
 1295             double dt = t2 - t1;
 
 1296             Point p2 = poly.interpolate(k-1, (l - arcLength[k-1]) / (d - arcLength[k-1]));
 
 1297             Point sum1 = 0.5 * dt * (p1 + p2);
 
 1298             Point sumt = dt / 6.0 * (p1*(2.0*t1+t2) + p2*(t1+2.0*t2));
 
 1299             integrals[l-1] += sum1 - sumt;
 
 1300             integrals[l] += sumt;
 
 1301             if(isOpenPolygon && l==1)
 
 1303                 integrals[0] +=  poly[0] - integrals[1];
 
 1308             if(isOpenPolygon && l==segmentCount)
 
 1310                 integrals[segmentCount] += integrals[segmentCount-1];
 
 1313         if(d < l && l <= segmentCount)
 
 1315             double t2 = std::fmod(d, 1.0);
 
 1316             double dt = t2 - t1;
 
 1318             Point sum1 = 0.5 * dt * (p1 + p2);
 
 1319             Point sumt = dt / 6.0 * (p1*(2.0*t1+t2) + p2*(t1+2.0*t2));
 
 1320             integrals[l-1] += sum1 - sumt;
 
 1321             integrals[l] += sumt;
 
 1329         integrals[segmentCount] += poly[size-1] - integrals[segmentCount-1];
 
 1330         integrals[1] -= integrals[0] / 6.0;
 
 1331         integrals[segmentCount-1] -= integrals[segmentCount] / 6.0;
 
 1333         ArrayVector<double> g(segmentCount);
 
 1334         double b = 2.0 / 3.0;
 
 1335         simple.push_back(poly[0]);
 
 1336         simple.push_back(integrals[1] / b);
 
 1337         for(
int k=2; k<segmentCount; ++k)
 
 1339             g[k] = 1.0 / 6.0 / b;
 
 1340             b = 2.0 / 3.0 - g[k] / 6.0;
 
 1341             simple.push_back((integrals[k] - simple[k-1] / 6.0) / b);
 
 1343         for(
int k = segmentCount-2; k >= 1; --k)
 
 1345             simple[k] -= g[k+1] * simple[k+1];
 
 1348         simple.push_back(poly[size-1]);
 
 1352         integrals[0] += integrals[segmentCount];
 
 1354         int initializationSteps = std::min(segmentCount, 5);
 
 1355         ArrayVector<Point> p(segmentCount+2*initializationSteps);
 
 1356         double b = 0.6220084679281461,
 
 1357                g = 0.26794919243112275;
 
 1358         p[0] = integrals[0] / b;
 
 1360         for(
int k=1; k<segmentCount+2*initializationSteps; ++k)
 
 1362             p[k] = (integrals[k % segmentCount] - p[k-1] / 6.0) / b;
 
 1364         for(
int k = segmentCount+2*initializationSteps-2; k >= initializationSteps; --k)
 
 1369         for(
int k=segmentCount; k<segmentCount+initializationSteps; ++k)
 
 1370             simple.push_back(p[k]);
 
 1371         for(
int k=initializationSteps; k<=segmentCount; ++k)
 
 1372             simple.push_back(p[k]);
 
 1378 template<
class Po
intArray>
 
 1379 void resamplePolygonLinearInterpolation(
 
 1380     const PointArray &poly, PointArray &simple, 
double desiredPointDistance)
 
 1382     int size = poly.size();
 
 1389     ArrayVector<double> arcLengths;
 
 1390     poly.arcLengthList(arcLengths);
 
 1392     int steps = int(
std::ceil(arcLengths[size-1] / desiredPointDistance));
 
 1393     double newStep = arcLengths[size-1] / steps;
 
 1395     simple.push_back(poly[0]);
 
 1397     for(
int k=1; k<steps; ++k)
 
 1399         double currentArcLength = k*newStep;
 
 1400         for(; l < size; ++l)
 
 1402             if(arcLengths[l] >= currentArcLength)
 
 1405         double o = (arcLengths[l] - currentArcLength) / (arcLengths[l] - arcLengths[l-1]);
 
 1406         simple.push_back(o*poly[l-1] + (1.0-o)*poly[l]);
 
 1408     simple.push_back(poly[size-1]);
 
 1413 template<
class Po
intArray>
 
 1414 void resamplePolygonExponentialFilter(
 
 1415     const PointArray &poly, PointArray &simple, 
double scale, 
double desiredPointDistance)
 
 1417     int size = poly.size();
 
 1424     bool isOpenPolygon = !poly.closed();
 
 1426     typedef typename PointArray::value_type Point;
 
 1427     ArrayVector<Point> pforward(size), pbackward(size);
 
 1428     ArrayVector<double> wforward(size), wbackward(size), weights(size-1);
 
 1429     for(
int k=0; k < size - 1; ++k)
 
 1430         weights[k] = 
std::exp(-(poly[k] - poly[k+1]).magnitude()/scale);
 
 1435     for(
int k=1; k < size; ++k)
 
 1437         p = poly[k] + weights[k-1]*p;
 
 1438         w = 1.0 + weights[k-1]*w;
 
 1445     for(
int k=size-2; k>=0; --k)
 
 1447         p = poly[k] + weights[k]*p;
 
 1448         w = 1.0 + weights[k]*w;
 
 1450     pbackward[size-1] = p;
 
 1451     wbackward[size-1] = w;
 
 1456         std::swap(wbackward[size-1], wforward[0]);
 
 1457         std::swap(pbackward[size-1], pforward[0]);
 
 1458         pforward[0] = 2.0*wforward[0]*poly[0] - pforward[0];
 
 1459         pbackward[size-1] = 2.0*wbackward[size-1]*poly[size-1] - pbackward[size-1];
 
 1463     for(
int k=1; k < size; ++k)
 
 1465         pforward[k] = poly[k] + weights[k-1]*pforward[k-1];
 
 1466         wforward[k] = 1.0 + weights[k-1]*wforward[k-1];
 
 1468     for(
int k=size-2; k >= 0; --k)
 
 1470         pbackward[k] = poly[k] + weights[k]*pbackward[k+1];
 
 1471         wbackward[k] = 1.0 + weights[k]*wbackward[k+1];
 
 1475     p = (pforward[0]+weights[0]*pbackward[1]) / (wforward[0] + weights[0]*wbackward[1]);
 
 1476     simple.push_back(p);
 
 1478     Point pend = isOpenPolygon
 
 1479                    ? (weights[size-2]*pforward[size-2]+pbackward[size-1]) /
 
 1480                      (weights[size-2]*wforward[size-2] + wbackward[size-1])
 
 1483     ArrayVector<double> arcLength;
 
 1484     double length = 0.0;
 
 1485     arcLength.push_back(length);
 
 1486     for(
int k=1; k<size-1; ++k)
 
 1488         Point pc = (pforward[k]+weights[k]*pbackward[k+1]) / (wforward[k] + weights[k]*wbackward[k+1]);
 
 1489         length += (pc - p).magnitude();
 
 1490         arcLength.push_back(length);
 
 1493     length += (p-pend).magnitude();
 
 1494     arcLength.push_back(length);
 
 1499     int steps = int(
std::floor(arcLength[size-1] / desiredPointDistance+0.5));
 
 1500     double newStep = arcLength[size-1] / steps;
 
 1503     for(
int k=1; k < steps; ++k)
 
 1505         double currentArcLength = k*newStep;
 
 1506         for(; l < size; ++l)
 
 1508             if(arcLength[l] >= currentArcLength)
 
 1511         double w = weights[l-1];
 
 1512         double o = (arcLength[l] - currentArcLength) / (arcLength[l] - arcLength[l-1]);
 
 1513         double wl = std::pow(w, 1.0-o);
 
 1514         double wr = std::pow(w, o);
 
 1515         simple.push_back((wl*pforward[l-1]+wr*pbackward[l]) / (wl*wforward[l-1] + wr*wbackward[l]));
 
 1517     simple.push_back(pend);
 
 1524 template<
class ArcLengthList, 
class Po
intList>
 
 1525 typename PointList::value_type
 
 1526 singleGaussianConvolvePolygonReflective(
 
 1527     const ArcLengthList &arcLengthList,
 
 1528     const PointList &pointList,
 
 1529     int i, 
double arcLengthPos,
 
 1530     const Gaussian<double> &g)
 
 1532     typedef typename PointList::value_type ValueType;
 
 1534     ValueType 
sum(vigra::NumericTraits<ValueType>::zero());
 
 1537     int size = arcLengthList.size(),
 
 1538         lastIndex = size - 1;
 
 1539     double reflectLength = 2.0*arcLengthList[lastIndex];
 
 1541     ValueType reflectPoint = 2.0*pointList[lastIndex];
 
 1542     for(
int j = i; 
true; ++j)
 
 1544         int k = (j > lastIndex)
 
 1547         double pos = arcLengthList[k];
 
 1548         ValueType point = pointList[k];
 
 1551             pos = reflectLength - pos;
 
 1552             point = reflectPoint - point;
 
 1554         double diff = pos - arcLengthPos;
 
 1555         if(diff > g.radius())
 
 1562     reflectPoint = 2.0*pointList[0];
 
 1563     for(
int j = i - 1; 
true; --j)
 
 1566         double pos = arcLengthList[k];
 
 1567         ValueType point = pointList[k];
 
 1571             point = reflectPoint - point;
 
 1573         double diff = pos - arcLengthPos;
 
 1574         if(diff < -g.radius())
 
 1584 template<
class ArcLengthList, 
class Po
intList>
 
 1585 typename PointList::value_type
 
 1586 singleGaussianConvolvePolygonCyclic(
 
 1587     const ArcLengthList &arcLengthList,
 
 1588     const PointList &pointList,
 
 1589     int i, 
double arcLengthPos,
 
 1590     const Gaussian<double> &g)
 
 1592     typedef typename PointList::value_type ValueType;
 
 1594     ValueType 
sum(vigra::NumericTraits<ValueType>::zero());
 
 1597     int size = arcLengthList.size() - 1,
 
 1598         lastIndex = size - 1;
 
 1599     double totalLength = arcLengthList[size];
 
 1601     for(
int j = i; 
true; ++j)
 
 1604         double pos = j > lastIndex
 
 1605                         ? arcLengthList[k] + totalLength
 
 1607         ValueType point = pointList[k];
 
 1608         double diff = pos - arcLengthPos;
 
 1609         if(diff > g.radius())
 
 1616     for(
int j = i - 1; 
true; --j)
 
 1618         int k = (j + size) % size;
 
 1620                        ? arcLengthList[k] - totalLength
 
 1622         ValueType point = pointList[k];
 
 1623         double diff = pos - arcLengthPos;
 
 1624         if(diff < -g.radius())
 
 1636 template<
class Po
intArray>
 
 1637 void resamplePolygonGaussianFilter(
 
 1638     const PointArray &poly, PointArray &simple, 
double scale, 
double desiredPointDistance)
 
 1640     int size = poly.size();
 
 1647     ArrayVector<double> arcLengths;
 
 1648     poly.arcLengthList(arcLengths);
 
 1650     Gaussian<double> g(scale);
 
 1652     vigra_precondition(arcLengths[size-1] > g.radius(),
 
 1653         "resamplePolygonGaussianFilter(): Filter longer than polygon.");
 
 1655     bool isOpenPolygon = !poly.closed();
 
 1657     int steps = int(
std::ceil(arcLengths[size-1] / desiredPointDistance));
 
 1658     double newStep = arcLengths[size-1] / steps;
 
 1661     for(
int k=0; k<steps; ++k)
 
 1663         double currentArcLength = k*newStep;
 
 1664         for(; l < size; ++l)
 
 1666             if(arcLengths[l] >= currentArcLength)
 
 1670             simple.push_back(detail::singleGaussianConvolvePolygonReflective(arcLengths, poly, l, currentArcLength, g));
 
 1672             simple.push_back(detail::singleGaussianConvolvePolygonCyclic(arcLengths, poly, l, currentArcLength, g));
 
 1675         simple.push_back(detail::singleGaussianConvolvePolygonReflective(arcLengths, poly, size-1, arcLengths[size-1], g));
 
 1677         simple.push_back(simple[0]);
 
 1684 template<
class Po
int>
 
 1685 Point spline3Integral(Point 
const & p1, Point 
const & p2, 
double t1, 
double t2)
 
 1687     StaticPolynomial<5, double> p[2];
 
 1688     p[0][0] = p[1][0] = 0.0;
 
 1691         return (t1 - t2) / 120.0 *
 
 1692                (p1 * (-80.0 + t1*(80.0 + 2.0*t2*(t2 - 10.0) + t1*(3.0*t2 - 30.0 + 4.0*t1)) + t2*(40.0 + t2*(t2 - 10.0))) +
 
 1693                 p2 * (-80.0 + t1*(40.0 + t2*(3.0*t2 - 20.0) + t1*(2.0*t2 - 10.0 + t1)) + t2*(80.0 + t2*(4.0*t2 - 30.0))));
 
 1697         return (t2 - t1) / 120.0 *
 
 1698                (p1 * (40.0 + t1*(2.0*t2*(3.0*t2 - 10.0) + t1*(9.0*t2 - 30.0 + 12.0*t1)) + t2*t2*(3.0*t2 - 10.0)) +
 
 1699                 p2 * (40.0 + t1*(t2*(9.0*t2 - 20.0) + t1*(6.0*t2 - 10.0 + 3.0*t1)) + t2*t2*(12.0*t2 - 30.0)));
 
 1703 template<
class ArcLengthList, 
class Po
intList>
 
 1704 typename PointList::value_type
 
 1705 singleSpline3ConvolvePolygon(
 
 1706     const ArcLengthList &arcLengthList,
 
 1707     const PointList &pointList,
 
 1708     int left, 
int center, 
int right)
 
 1710     typedef typename PointList::value_type ValueType;
 
 1712     ValueType 
sum(vigra::NumericTraits<ValueType>::zero());
 
 1713     double arcLengthPos = arcLengthList[center];
 
 1714     for(
int j = center + 1; j <= right; ++j)
 
 1716         double t1 = arcLengthList[j-1] - arcLengthPos,
 
 1717                t2 = arcLengthList[j] - arcLengthPos;
 
 1718         sum += spline3Integral(pointList[j-1], pointList[j], t1, t2);
 
 1720     for(
int j = center - 1; j >= left; --j)
 
 1722         double t1 = arcLengthPos - arcLengthList[j+1],
 
 1723                t2 = arcLengthPos - arcLengthList[j];
 
 1724         sum -= spline3Integral(-pointList[j+1], -pointList[j], t1, t2);
 
 1732 template<
class Po
intArray>
 
 1733 void polygonSplineControlPoints(
 
 1734     const PointArray &poly, PointArray &splinePoints, 
int segmentCount)
 
 1736     typedef typename PointArray::value_type Point;
 
 1738     int size = poly.size();
 
 1739     vigra_precondition(size >= 4,
 
 1740         "polygonSplineControlPoints(): Polygon must have at least 4 points.");
 
 1742     bool isOpenPolygon = !poly.closed();
 
 1744     ArrayVector<double> arcLength;
 
 1745     poly.arcLengthList(arcLength);
 
 1746     double totalLength = segmentCount / arcLength[size-1];
 
 1747     for(
int k=0; k<size; ++k)
 
 1748         arcLength[k] *= totalLength;
 
 1750     PointArray augmentedPoly;
 
 1751     augmentedPoly.push_back(poly[0]);
 
 1753     ArrayVector<double> augmentedArcLength;
 
 1754     augmentedArcLength.push_back(0.0);
 
 1756     ArrayVector<int> splineIndices(segmentCount + 1);
 
 1757     splineIndices[0] = 0;
 
 1759     for(
int k=1; k<size-1; ++k)
 
 1761         double d = arcLength[k];
 
 1764             augmentedPoly.push_back(poly.interpolate(k-1, (l - arcLength[k-1]) / (d - arcLength[k-1])));
 
 1765             augmentedArcLength.push_back(l);
 
 1766             splineIndices[l] = augmentedPoly.size()-1;
 
 1769         augmentedPoly.push_back(poly[k]);
 
 1770         augmentedArcLength.push_back(d);
 
 1773             splineIndices[l] = augmentedPoly.size()-1;
 
 1777     augmentedPoly.push_back(poly[size-1]);
 
 1778     augmentedArcLength.push_back(segmentCount);
 
 1779     splineIndices[segmentCount] = augmentedPoly.size()-1;
 
 1780     size = augmentedPoly.size();
 
 1782     ArrayVector<Point> integrals(segmentCount+1);
 
 1785         integrals[0] = augmentedPoly[0];
 
 1786         PointArray reflectedPoly;
 
 1787         Point reflectPoint = 2.0*poly[0];
 
 1788         ArrayVector<double> reflectedArcLength;
 
 1789         for(
int k=-splineIndices[1]; k <= splineIndices[3]; ++k)
 
 1793                 reflectedPoly.push_back(reflectPoint - augmentedPoly[-k]);
 
 1794                 reflectedArcLength.push_back(-augmentedArcLength[-k]);
 
 1798                 reflectedPoly.push_back(augmentedPoly[k]);
 
 1799                 reflectedArcLength.push_back(augmentedArcLength[k]);
 
 1802         integrals[1] = detail::singleSpline3ConvolvePolygon(reflectedArcLength, reflectedPoly,
 
 1803                                     0, 2*splineIndices[1], splineIndices[1] + splineIndices[3]);
 
 1805         reflectPoint = 2.0*augmentedPoly[size-1];
 
 1806         for(
int k=size-2; k>=splineIndices[segmentCount-1]; --k)
 
 1808             augmentedPoly.push_back(reflectPoint - augmentedPoly[k]);
 
 1809             augmentedArcLength.push_back(2.0*segmentCount - augmentedArcLength[k]);
 
 1811         integrals[segmentCount-1] = detail::singleSpline3ConvolvePolygon(augmentedArcLength, augmentedPoly,
 
 1812                splineIndices[segmentCount-3], splineIndices[segmentCount-1],
 
 1813                2*splineIndices[segmentCount] - splineIndices[segmentCount-1]);
 
 1814         integrals[segmentCount] = augmentedPoly[size-1];
 
 1818         PointArray wrappedPoly;
 
 1819         ArrayVector<double> wrappedArcLength;
 
 1820         for(
int k=splineIndices[segmentCount-1]; k < splineIndices[segmentCount]; ++k)
 
 1822             wrappedPoly.push_back(augmentedPoly[k]);
 
 1823             wrappedArcLength.push_back(augmentedArcLength[k] - segmentCount);
 
 1825         int indexShift = wrappedPoly.size();
 
 1826         for(
int k=0; k <= splineIndices[3]; ++k)
 
 1828             wrappedPoly.push_back(augmentedPoly[k]);
 
 1829             wrappedArcLength.push_back(augmentedArcLength[k]);
 
 1831         integrals[1] = detail::singleSpline3ConvolvePolygon(wrappedArcLength, wrappedPoly,
 
 1832                              0, splineIndices[1] + indexShift, splineIndices[3] + indexShift);
 
 1834         for(
int k=1; k <= splineIndices[2]; ++k)
 
 1836             augmentedPoly.push_back(augmentedPoly[k]);
 
 1837             augmentedArcLength.push_back(segmentCount + augmentedArcLength[k]);
 
 1839         integrals[segmentCount-1] = detail::singleSpline3ConvolvePolygon(augmentedArcLength, augmentedPoly,
 
 1840                splineIndices[segmentCount-3], splineIndices[segmentCount-1],
 
 1841                splineIndices[segmentCount] + splineIndices[1]);
 
 1842         integrals[0] = detail::singleSpline3ConvolvePolygon(augmentedArcLength, augmentedPoly,
 
 1843                splineIndices[segmentCount-2], splineIndices[segmentCount],
 
 1844                splineIndices[segmentCount] + splineIndices[2]);
 
 1847     for(
int k=2; k <= segmentCount-2; ++k)
 
 1848         integrals[k] = detail::singleSpline3ConvolvePolygon(augmentedArcLength, augmentedPoly,
 
 1849                                     splineIndices[k-2], splineIndices[k], splineIndices[k+2]);
 
 1851     BSpline<7, double> spline7;
 
 1854         int solutionSize = segmentCount + 1;
 
 1855         Matrix<double> m(solutionSize, solutionSize),
 
 1856                     rhs(solutionSize, 2),
 
 1857                     solution(solutionSize, 2);
 
 1858         for(
int k=0; k<solutionSize; ++k)
 
 1860             for(
int l=-3; l<=3; ++l)
 
 1864                     m(k, 0) += 2.0*spline7(l);
 
 1865                     m(k, 
abs(k+l)) -= spline7(l);
 
 1867                 else if(k + l >= solutionSize)
 
 1869                     m(k, solutionSize - 1) += 2.0*spline7(l);
 
 1870                     m(k, 2*solutionSize - k - l - 2) -= spline7(l);
 
 1873                     m(k,k+l) += spline7(l);
 
 1875             rhs(k, 0) = integrals[k][0];
 
 1876             rhs(k, 1) = integrals[k][1];
 
 1881         for(
int k=0; k<solutionSize; ++k)
 
 1883             splinePoints.push_back(Point(solution(k,0), solution(k,1)));
 
 1885         splinePoints.push_back(2.0*splinePoints[solutionSize-1] - splinePoints[solutionSize-2]);
 
 1886         splinePoints.insert(splinePoints.begin(), 2.0*splinePoints[0] - splinePoints[1]);
 
 1890         int solutionSize = segmentCount;
 
 1891         Matrix<double> m(solutionSize, solutionSize),
 
 1892                     rhs(solutionSize, 2),
 
 1893                     solution(solutionSize, 2);
 
 1894         for(
int k=0; k<solutionSize; ++k)
 
 1896             for(
int l=-3; l<=3; ++l)
 
 1897                 m(k, (k+l+solutionSize) % solutionSize) = spline7(l);
 
 1898             rhs(k, 0) = integrals[k][0];
 
 1899             rhs(k, 1) = integrals[k][1];
 
 1903         for(
int k=0; k<solutionSize; ++k)
 
 1905             splinePoints.push_back(Point(solution(k,0), solution(k,1)));
 
 1907         splinePoints.push_back(splinePoints[0]);
 
 1920 ostream & operator<<(ostream & s, vigra::Polygon<T> 
const & a)
 
 1922     for(std::size_t k=0; k<a.size()-1; ++k)
 
reference back()
Definition: array_vector.hxx:321
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product 
Definition: rgbvalue.hxx:906
void transpose(const MultiArrayView< 2, T, C1 > &v, MultiArrayView< 2, T, C2 > &r)
Definition: matrix.hxx:965
Int32 roundi(FixedPoint16< IntBits, OverflowHandling > v)
rounding to the nearest integer. 
Definition: fixedpoint.hxx:1775
Diff2D operator-(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:711
double arcLengthQuantile(double quantile) const 
Definition: polygon.hxx:379
void extractContour(MultiArrayView< 2, T, S > const &label_image, Shape2 const &anchor_point, PointArray &contour_points)
Create a polygon from the interpixel contour of a labeled region. 
Definition: polygon.hxx:766
const difference_type & shape() const 
Definition: multi_array.hxx:1648
bool empty() const
Definition: array_vector.hxx:351
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
const_iterator begin() const
Definition: array_vector.hxx:223
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude) 
Definition: fftw3.hxx:1044
int round(FixedPoint< IntBits, FracBits > v)
rounding to the nearest integer. 
Definition: fixedpoint.hxx:683
reverse_iterator rend()
Definition: array_vector.hxx:279
Diff2D operator+(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:739
const_reverse_iterator crend() const
Definition: array_vector.hxx:300
Point interpolate(unsigned int index, double offset) const 
Definition: polygon.hxx:187
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
const_reverse_iterator crbegin() const
Definition: array_vector.hxx:293
Definition: polygon.hxx:78
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude) 
Definition: fftw3.hxx:1037
reference operator[](difference_type i)
Definition: array_vector.hxx:335
Definition: array_vector.hxx:58
NumericTraits< T >::Promote sq(T t)
The square function. 
Definition: mathutil.hxx:382
reference front()
Definition: array_vector.hxx:307
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements 
Definition: tinyvector.hxx:2073
bool isInside(difference_type const &p) const 
Definition: multi_array.hxx:1717
bool contains(const_reference point, coordinate_type tolerance) const 
Definition: polygon.hxx:524
bool closeAtTolerance(T1 l, T2 r, typename PromoteTraits< T1, T2 >::Promote epsilon)
Tolerance based floating-point equality. 
Definition: mathutil.hxx:1638
const_iterator cend() const
Definition: array_vector.hxx:258
const_iterator cbegin() const
Definition: array_vector.hxx:251
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude) 
Definition: fftw3.hxx:1002
Base class for, and view to, vigra::MultiArray. 
Definition: multi_array.hxx:704
reverse_iterator rbegin()
Definition: array_vector.hxx:265
const_iterator end() const
Definition: array_vector.hxx:237
size_type size() const
Definition: array_vector.hxx:358
void convexHull(const PointArray1 &points, PointArray2 &convex_hull)
Compute convex hull of a 2D polygon. 
Definition: polygon.hxx:838
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up. 
Definition: fixedpoint.hxx:675
void fillPolygon(Polygon< Point > const &p, MultiArrayView< 2, T, S > &output_image, Value value)
Render closed polygon p into the image output_image. 
Definition: polygon.hxx:1005
int floor(FixedPoint< IntBits, FracBits > v)
rounding down. 
Definition: fixedpoint.hxx:667
bool closed() const 
Returns true iff the last and first points are equal or the polygon is empty. 
Definition: polygon.hxx:177
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root. 
Definition: fixedpoint.hxx:616