Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Mask.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This software is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public
22  * License along with this software. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 // for debugging
28 #include <iostream>
29 #include <stdio.h>
30 
31 #include "Mask.h"
32 
33 #include <iostream>
34 #include <vector>
37 
38 namespace HuginBase {
39 
41 {
42  if(m_polygon.size()<3)
43  return false;
44  if(!m_boundingBox.contains(vigra::Point2D(p.x,p.y)))
45  return false;
46  int wind=getWindingNumber(p);
47  if(m_invert)
48  return wind==0;
49  else
50  return wind!=0;
51 };
52 
54 {
55  // algorithm is modified version of winding number method
56  // described at http://www.softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm
57  // Copyright 2001, softSurfer (www.softsurfer.com)
58  // This code may be freely used and modified for any purpose
59  // providing that this copyright notice is included with it.
60  if(m_polygon.size()<3)
61  return 0;
62  int wind=0;
64  for(unsigned int i=0;i<m_polygon.size();i++)
65  {
67  if(a.y<=p.y)
68  {
69  if(b.y>p.y)
70  if((b.x-a.x)*(p.y-a.y)<(p.x-a.x)*(b.y-a.y))
71  wind++;
72  }
73  else
74  {
75  if(b.y<=p.y)
76  if((b.x-a.x)*(p.y-a.y)>(p.x-a.x)*(b.y-a.y))
77  wind--;
78  };
79  a=b;
80  };
81  return wind;
82 };
83 
85 {
86  if(m_polygon.size()<2)
87  return 0;
88  MaskPolygon diffPoly;
89  unsigned int count=m_polygon.size();
90  for(unsigned int i=0;i<count;i++)
91  {
92  diffPoly.addPoint(m_polygon[(i+1)%count]-m_polygon[i]);
93  };
94  return diffPoly.getWindingNumber(hugin_utils::FDiff2D(0,0));
95 };
96 
98 {
99  return (m_maskType==Mask_positive) ||
101 };
102 
104 {
105  m_polygon=newMask;
106  calcBoundingBox();
107 };
108 
110 {
111  m_polygon.push_back(p);
112  calcBoundingBox();
113 };
114 
115 void MaskPolygon::insertPoint(const unsigned int index, const hugin_utils::FDiff2D p)
116 {
117  if(index<=m_polygon.size())
118  {
119  m_polygon.insert(m_polygon.begin()+index,p);
120  calcBoundingBox();
121  };
122 };
123 
124 
125 void MaskPolygon::removePoint(const unsigned int index)
126 {
127  if(index<m_polygon.size())
128  {
129  m_polygon.erase(m_polygon.begin()+index);
130  calcBoundingBox();
131  };
132 };
133 
134 void MaskPolygon::movePointTo(const unsigned int index, const hugin_utils::FDiff2D p)
135 {
136  if(index<m_polygon.size())
137  {
138  m_polygon[index].x=p.x;
139  m_polygon[index].y=p.y;
140  calcBoundingBox();
141  };
142 };
143 
144 void MaskPolygon::movePointBy(const unsigned int index, const hugin_utils::FDiff2D diff)
145 {
146  if(index<m_polygon.size())
147  {
148  m_polygon[index].x+=diff.x;
149  m_polygon[index].y+=diff.y;
150  calcBoundingBox();
151  };
152 };
153 
154 void MaskPolygon::scale(const double factorx,const double factory)
155 {
156  for(unsigned int i=0;i<m_polygon.size();i++)
157  {
158  m_polygon[i].x*=factorx;
159  m_polygon[i].y*=factory;
160  };
161  calcBoundingBox();
162 };
163 
165 {
166  double xnew,ynew;
167  VectorPolygon newPoly;
168  for(unsigned int i=0;i<m_polygon.size();i++)
169  {
170  if(trans.transformImgCoord(xnew,ynew,m_polygon[i].x,m_polygon[i].y))
171  {
172  newPoly.push_back(hugin_utils::FDiff2D(xnew,ynew));
173  };
174  };
175  m_polygon=newPoly;
176  calcBoundingBox();
177 };
178 
179 void MaskPolygon::subSample(const double max_distance)
180 {
181  if(m_polygon.size()<3)
182  return;
183  VectorPolygon oldPoly=m_polygon;
184  unsigned int count=oldPoly.size();
185  m_polygon.clear();
186  for(unsigned int i=0;i<count;i++)
187  {
188  addPoint(oldPoly[i]);
189  hugin_utils::FDiff2D p1=oldPoly[i];
190  hugin_utils::FDiff2D p2=oldPoly[(i+1)%count];
191  double distance=norm(p2-p1);
192  if(distance>max_distance)
193  {
194  //add intermediate points
195  double currentDistance=max_distance;
196  while(currentDistance<distance)
197  {
198  hugin_utils::FDiff2D p_new=p1+(p2-p1)*currentDistance/distance;
199  addPoint(p_new);
200  currentDistance+=max_distance;
201  };
202  };
203  };
204 };
205 
207 {
208  if(!m_polygon.empty())
209  {
210  m_boundingBox.setUpperLeft(vigra::Point2D(m_polygon[0].x,m_polygon[0].y));
211  m_boundingBox.setLowerRight(vigra::Point2D(m_polygon[0].x+1,m_polygon[0].y+1));
212  if(m_polygon.size()>1)
213  {
214  for(unsigned int i=1;i<m_polygon.size();i++)
215  {
216  m_boundingBox|=vigra::Point2D(m_polygon[i].x,m_polygon[i].y);
217  };
218  };
219  //adding a small border to get no rounding error because polygon coordinates are float
220  //numbers, but bounding box has integer coordinates
221  m_boundingBox.addBorder(2);
222  };
223 };
224 
225 //helper function for clipping
227 {
232 };
233 
234 bool clip_isSide(const hugin_utils::FDiff2D p, const vigra::Rect2D r, const clipSide side)
235 {
236  switch(side){
237  case clipLeft:
238  return p.x>=r.left();
239  case clipRight:
240  return p.x<=r.right();
241  case clipTop:
242  return p.y>=r.top();
243  case clipBottom:
244  return p.y<=r.bottom();
245  };
246  //this should never happens
247  return false;
248 }
249 
251 {
252  double a;
253  double b;
254  double xnew;
255  double ynew;
256  if(q.x-p.x==0)
257  {
258  a=0;
259  b=p.y;
260  }
261  else
262  {
263  a=(q.y-p.y)/(q.x-p.x);
264  b=p.y-p.x*a;
265  };
266  switch(side){
267  case clipLeft:
268  xnew=r.left();
269  ynew=xnew*a+b;
270  break;
271  case clipRight:
272  xnew=r.right();
273  ynew=xnew*a+b;
274  break;
275  case clipTop:
276  ynew=r.top();
277  if(a!=0)
278  xnew=(ynew-b)/a;
279  else
280  xnew=p.x;
281  break;
282  case clipBottom:
283  ynew=r.bottom();
284  if(a!=0)
285  xnew=(ynew-b)/a;
286  else
287  xnew=p.x;
288  break;
289  };
290  return hugin_utils::FDiff2D(xnew,ynew);
291 };
292 
293 VectorPolygon clip_onPlane(const VectorPolygon& polygon, const vigra::Rect2D r, const clipSide side)
294 {
295  if(polygon.size()<3)
296  {
297  return polygon;
298  };
299  hugin_utils::FDiff2D s=polygon[polygon.size()-1];
301  VectorPolygon newPolygon;
302  for(unsigned int i=0;i<polygon.size();i++)
303  {
304  p=polygon[i];
305  if(clip_isSide(p,r,side))
306  {
307  // point p is "inside"
308  if(!clip_isSide(s,r,side))
309  // and point s is "outside"
310  newPolygon.push_back(clip_getIntersection(p,s,r,side));
311  newPolygon.push_back(p);
312  }
313  else
314  {
315  //point p is "outside"
316  if(clip_isSide(s,r,side))
317  //ans point s is "inside"
318  newPolygon.push_back(clip_getIntersection(s,p,r,side));
319  };
320  s=p;
321  };
322  return newPolygon;
323 };
324 
325 bool MaskPolygon::clipPolygon(const vigra::Rect2D rect)
326 {
327  //clipping using Sutherland-Hodgman algorithm
332  calcBoundingBox();
333  return (m_polygon.size()>2);
334 };
335 
336 //helper function for clipping
343 bool clip_insideCircle(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D center, const double radius)
344 {
345  return p.squareDistance(center)<=radius*radius;
346 };
347 
355 std::vector<hugin_utils::FDiff2D> clip_getIntersectionCircle(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D s, const hugin_utils::FDiff2D center, const double radius)
356 {
357  std::vector<hugin_utils::FDiff2D> intersections;
358  hugin_utils::FDiff2D slope=s-p;
359  if(slope.squareLength()<1e-5)
360  {
361  return intersections;
362  };
363  hugin_utils::FDiff2D p2=p-center;
364  double dotproduct=p2.x*slope.x+p2.y*slope.y;
365  double root=sqrt(dotproduct*dotproduct-slope.squareLength()*(p2.squareLength()-radius*radius));
366  double t1=(-dotproduct+root)/slope.squareLength();
367  double t2=(-dotproduct-root)/slope.squareLength();
368  std::set<double> t;
369  if(t1>0 && t1<1)
370  {
371  t.insert(t1);
372  };
373  if(t2>0 && t2<1)
374  {
375  if(fabs(t2-t1)>1e-5)
376  {
377  t.insert(t2);
378  };
379  };
380  if(!t.empty())
381  {
382  for(std::set<double>::const_iterator it=t.begin();it!=t.end();++it)
383  {
384  intersections.push_back(p+slope*(*it));
385  };
386  };
387  return intersections;
388 };
389 
392 {
393  return asin((a.x*b.y-a.y*b.x)/(sqrt(a.squareLength())*sqrt(b.squareLength())));
394 };
395 
403 void generateArc(VectorPolygon& poly, const hugin_utils::FDiff2D s, const hugin_utils::FDiff2D center, const double radius, const bool clockwise)
404 {
405  if(poly.empty())
406  {
407  return;
408  };
409  hugin_utils::FDiff2D p=poly[poly.size()-1];
410  double maxDistance=5.0;
411  if(p.squareDistance(s)<maxDistance*maxDistance)
412  {
413  return;
414  };
415  double angle=atan2(p.y-center.y,p.x-center.x);
416  double final_angle=atan2(s.y-center.y,s.x-center.x);
417  //step 1 degree or less, so that max distance between 2 points is smaller than maxDistance
418  double step=std::min<double>(PI/180,atan2(maxDistance,radius));
419  if(!clockwise)
420  {
421  while(final_angle<angle)
422  {
423  final_angle+=2*PI;
424  };
425  angle+=step;
426  while(angle<final_angle)
427  {
428  poly.push_back(hugin_utils::FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y));
429  angle+=step;
430  };
431  }
432  else
433  {
434  while(final_angle>angle)
435  {
436  final_angle-=2*PI;
437  };
438  angle-=step;
439  while(angle>final_angle)
440  {
441  poly.push_back(hugin_utils::FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y));
442  angle-=step;
443  };
444  };
445 };
446 
447 bool MaskPolygon::clipPolygon(const hugin_utils::FDiff2D center,const double radius)
448 {
449  if(radius<=0 || m_polygon.size()<3)
450  {
451  return false;
452  };
454  bool s_inside=clip_insideCircle(s,center,radius);
456  VectorPolygon newPolygon;
457  bool needsFinalArc=false;
458  double angleCovered=0;
459  double angleCoveredOffset=0;
460  for(unsigned int i=0;i<m_polygon.size();i++)
461  {
462  p=m_polygon[i];
463  bool p_inside=clip_insideCircle(p,center,radius);
464  if(p_inside)
465  {
466  if(s_inside)
467  {
468  //both points inside
469  newPolygon.push_back(p);
470  }
471  else
472  {
473  //line crosses circles from outside
474  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(p,s,center,radius);
475  DEBUG_ASSERT(points.size()==1);
476  angleCovered+=angle_between(s-center,points[0]-center);
477  if(newPolygon.empty())
478  {
479  needsFinalArc=true;
480  angleCoveredOffset=angleCovered;
481  }
482  else
483  {
484  generateArc(newPolygon,points[0],center,radius,angleCovered<0);
485  };
486  newPolygon.push_back(points[0]);
487  newPolygon.push_back(p);
488  };
489  }
490  else
491  {
492  if(!s_inside)
493  {
494  //both points outside of circle
495  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
496  //intersection can only be zero points or 2 points
497  if(points.size()>1)
498  {
499  angleCovered+=angle_between(s-center,points[0]-center);
500  if(newPolygon.empty())
501  {
502  needsFinalArc=true;
503  angleCoveredOffset=angleCovered;
504  }
505  else
506  {
507  generateArc(newPolygon,points[0],center,radius,angleCovered<0);
508  };
509  newPolygon.push_back(points[0]);
510  newPolygon.push_back(points[1]);
511  angleCovered=angle_between(points[1]-center,p-center);
512  }
513  else
514  {
515  angleCovered+=angle_between(s-center,p-center);
516  };
517  }
518  else
519  {
520  //line segment intersects circle from inside
521  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
522  angleCovered=0;
523  DEBUG_ASSERT(points.size()==1);
524  newPolygon.push_back(points[0]);
525  };
526  };
527  s=p;
528  s_inside=p_inside;
529  };
530  if(needsFinalArc && newPolygon.size()>1)
531  {
532  generateArc(newPolygon,newPolygon[0],center,radius,(angleCovered+angleCoveredOffset)<0);
533  };
534  m_polygon=newPolygon;
535  calcBoundingBox();
536  return (m_polygon.size()>2);
537 };
538 
539 void MaskPolygon::rotate90(bool clockwise,unsigned int maskWidth,unsigned int maskHeight)
540 {
541  for(unsigned int i=0;i<m_polygon.size();i++)
542  {
543  if(clockwise)
544  {
546  m_polygon[i].x=maskHeight-p.y;
547  m_polygon[i].y=p.x;
548  }
549  else
550  {
552  m_polygon[i].x=p.y;
553  m_polygon[i].y=maskWidth-p.x;
554  };
555  };
556  calcBoundingBox();
557 };
558 
559 unsigned int MaskPolygon::FindPointNearPos(const hugin_utils::FDiff2D p, const double tol) const
560 {
561  if(m_polygon.empty())
562  return UINT_MAX;
564  unsigned int j=m_polygon.size()-1;
566  for(unsigned int i=0;i<m_polygon.size();i++)
567  {
568  p1=m_polygon[i];
569  // find intersection of perpendicular through point p and line between point i and j
570  hugin_utils::FDiff2D diff=p2-p1;
571  if(norm(diff)<0.001)
572  continue;
573  double u=((p.x-p1.x)*(p2.x-p1.x)+(p.y-p1.y)*(p2.y-p1.y))/hugin_utils::sqr(norm(diff));
574  if((u>=0.1) && (u<=0.9))
575  {
576  // intersection is between p1 and p2
577  hugin_utils::FDiff2D footpoint=p1+diff*u;
578  // now check distance between intersection and p
579  if(norm(p-footpoint)<tol)
580  return i==0 ? j+1 : i;
581  };
582  j=i;
583  p2=p1;
584  };
585  return UINT_MAX;
586 };
587 
589 {
590  if (this == &otherPoly)
591  return *this;
592  setMaskType(otherPoly.getMaskType());
593  setMaskPolygon(otherPoly.getMaskPolygon());
594  setImgNr(otherPoly.getImgNr());
595  setInverted(otherPoly.isInverted());
596  return *this;
597 };
598 
599 const bool MaskPolygon::operator==(const MaskPolygon& otherPoly) const
600 {
601  return ((m_maskType == otherPoly.getMaskType()) && (m_polygon == otherPoly.getMaskPolygon()));
602 };
603 
604 bool MaskPolygon::parsePolygonString(const std::string& polygonStr)
605 {
606  m_polygon.clear();
607  if(polygonStr.length()==0)
608  return false;
609  std::stringstream is(polygonStr);
610  while(is.good())
611  {
612  double x;
613  if (is >> x)
614  {
615  double y;
616  if (is >> y)
617  {
618  m_polygon.push_back(hugin_utils::FDiff2D(x, y));
619  };
620  };
621  };
622  calcBoundingBox();
623  return m_polygon.size()>2;
624 };
625 
626 void MaskPolygon::printPolygonLine(std::ostream &o, const unsigned int newImgNr) const
627 {
628  o<<"k i"<<newImgNr<<" ";
629  o<<"t"<<(int)m_maskType<<" ";
630  o<<"p\"";
631  for(unsigned int i=0; i<m_polygon.size(); i++)
632  {
633  o<<m_polygon[i].x<<" "<<m_polygon[i].y;
634  if((i+1)!=m_polygon.size())
635  o<<" ";
636  };
637  o<<"\""<<std::endl;
638 };
639 
640 void LoadMaskFromStream(std::istream& stream,vigra::Size2D& imageSize, MaskPolygonVector &newMasks, size_t imgNr)
641 {
642  while (stream.good())
643  {
644  std::string line;
645  std::getline(stream,line);
646  switch (line[0])
647  {
648  case '#':
649  {
650  unsigned int w;
651  if (PTScriptParsing::getIntParam(w, line, "w"))
652  imageSize.setWidth(w);
653  unsigned int h;
654  if (PTScriptParsing::getIntParam(h, line, "h"))
655  imageSize.setHeight(h);
656  break;
657  }
658  case 'k':
659  {
660  HuginBase::MaskPolygon newPolygon;
661  //Ignore image number set in mask
662  newPolygon.setImgNr(imgNr);
663  unsigned int param;
664  if (PTScriptParsing::getIntParam(param,line,"t"))
665  {
667  }
668  std::string format;
669  if (PTScriptParsing::getPTParam(format,line,"p"))
670  {
671  if(newPolygon.parsePolygonString(format)) {
672  newMasks.push_back(newPolygon);
673  }
674  }
675  break;
676  }
677  default:
678  {
679  break;
680  }
681  }
682  }
683 };
684 
685 void SaveMaskToStream(std::ostream& stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
686 {
687  stream << "# w" << imageSize.width() << " h" << imageSize.height() << std::endl;
688  maskToWrite.printPolygonLine(stream, imgNr);
689 };
690 
691 } // namespace
void SaveMaskToStream(std::ostream &stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
save the mask into stream
Definition: Mask.cpp:685
double norm(T t)
Definition: hugin_math.h:175
bool isInside(const hugin_utils::FDiff2D p) const
checks if given point is inside of the stored polygon
Definition: Mask.cpp:40
void removePoint(const unsigned int index)
removes point at the position index from the polygon
Definition: Mask.cpp:125
bool parsePolygonString(const std::string &polygonStr)
parses the x and y positions from the given string
Definition: Mask.cpp:604
int getWindingNumber(const hugin_utils::FDiff2D p) const
returns the winding number of the polygon around point p
Definition: Mask.cpp:53
void movePointBy(const unsigned int index, const hugin_utils::FDiff2D diff)
relativ moves the point at position index by diff
Definition: Mask.cpp:144
std::vector< hugin_utils::FDiff2D > clip_getIntersectionCircle(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D s, const hugin_utils::FDiff2D center, const double radius)
returns intersection of line and circle
Definition: Mask.cpp:355
void LoadMaskFromStream(std::istream &stream, vigra::Size2D &imageSize, MaskPolygonVector &newMasks, size_t imgNr)
load the mask from stream
Definition: Mask.cpp:640
bool clip_insideCircle(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D center, const double radius)
check if point is inside circle
Definition: Mask.cpp:343
VectorPolygon clip_onPlane(const VectorPolygon &polygon, const vigra::Rect2D r, const clipSide side)
Definition: Mask.cpp:293
bool getIntParam(T &value, const std::string &line, const std::string &name)
void printPolygonLine(std::ostream &o, const unsigned int newImgNr) const
writes the complete k line which describes the mask to the stream, using the given newImgNr for the i...
Definition: Mask.cpp:626
T sqr(T t)
Definition: hugin_math.h:169
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
declaration of classes to work with mask
static char * line
Definition: svm.cpp:2784
bool getPTParam(std::string &output, const std::string &line, const std::string &parameter)
helper functions for parsing of a script line
#define PI
Header file for Khan&#39;s deghosting algorithm Copyright (C) 2009 Lukáš Jirkovský l...
Definition: khan.h:43
void calcBoundingBox()
calculates the bounding box of the polygon to speed up tests
Definition: Mask.cpp:206
VectorPolygon getMaskPolygon() const
returns vector with coordinates of the polygon
Definition: Mask.h:81
void generateArc(VectorPolygon &poly, const hugin_utils::FDiff2D s, const hugin_utils::FDiff2D center, const double radius, const bool clockwise)
adds an arc with given radius at the end of the polygon, the point is not added to the arc ...
Definition: Mask.cpp:403
void setMaskPolygon(const VectorPolygon &newMask)
set complete vector with all corrdinates of the polygon
Definition: Mask.cpp:103
bool isInverted() const
returns if mask is inverted
Definition: Mask.h:91
void setInverted(const bool inverted)
set mask to normal or inverted
Definition: Mask.h:89
vigra::Rect2D m_boundingBox
Definition: Mask.h:144
MaskType m_maskType
Definition: Mask.h:140
int getTotalWindingNumber() const
returns the total winding number of the polygon
Definition: Mask.cpp:84
void transformPolygon(const PTools::Transform &trans)
transforms the polygon coordinates by the given transformation
Definition: Mask.cpp:164
double angle_between(const hugin_utils::FDiff2D a, const hugin_utils::FDiff2D b)
calculates angle between vector a and b in radians
Definition: Mask.cpp:391
const bool operator==(const MaskPolygon &otherPoly) const
comparision operator
Definition: Mask.cpp:599
bool clip_isSide(const hugin_utils::FDiff2D p, const vigra::Rect2D r, const clipSide side)
Definition: Mask.cpp:234
VectorPolygon m_polygon
Definition: Mask.h:141
MaskType
enumeration with type of possible masks
Definition: Mask.h:56
unsigned int getImgNr() const
returns the associated image number, only used when loading a project, otherwise discarded ...
Definition: Mask.h:85
IMPEX double h[25][1024]
Definition: emor.cpp:169
bool clipPolygon(const vigra::Rect2D rect)
clips the polygon to the given rectangle
Definition: Mask.cpp:325
MaskPolygon & operator=(const MaskPolygon &otherPoly)
assign operator
Definition: Mask.cpp:588
TDiff2D< double > FDiff2D
Definition: hugin_math.h:150
std::vector< MaskPolygon > MaskPolygonVector
Definition: Mask.h:147
T squareLength() const
Return the square of the length of the vector.
Definition: hugin_math.h:141
hugin_utils::FDiff2D clip_getIntersection(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D q, const vigra::Rect2D r, const clipSide side)
Definition: Mask.cpp:250
void setImgNr(const unsigned int newImgNr)
sets the associated image number, only used when loading a project, otherwise discarded ...
Definition: Mask.h:87
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
void movePointTo(const unsigned int index, const hugin_utils::FDiff2D p)
moves the point at position index to the new absolute position p
Definition: Mask.cpp:134
void insertPoint(const unsigned int index, const hugin_utils::FDiff2D p)
insert point at the position index into the polygon
Definition: Mask.cpp:115
std::vector< hugin_utils::FDiff2D > VectorPolygon
vector, which stores coordinates of one polygon
Definition: Mask.h:39
void setMaskType(const MaskType newType)
sets mask type
Definition: Mask.h:77
Holds transformations for Image -&gt; Pano and the other way.
bool isPositive() const
returns true, if mask type is positive
Definition: Mask.cpp:97
void subSample(const double max_distance)
subsamples the polygon, so that the longest distance between 2 points is max_distance ...
Definition: Mask.cpp:179
unsigned int FindPointNearPos(const hugin_utils::FDiff2D p, const double tol) const
search a point which lies near the polygon line and return the index for inserting the new point ...
Definition: Mask.cpp:559
MaskType getMaskType() const
returns mask type
Definition: Mask.h:75
void rotate90(bool clockwise, unsigned int maskWidth, unsigned int maskHeight)
rotate the polygon by 90 degrees
Definition: Mask.cpp:539
void addPoint(const hugin_utils::FDiff2D p)
adds point at the end to the polygon
Definition: Mask.cpp:109
void scale(const double factorx, const double factory)
scales all polygon coordinates by factorx for x position and factory for y position ...
Definition: Mask.cpp:154
base class, which stores one mask polygon
Definition: Mask.h:52
T squareDistance(TDiff2D< T > other) const
Return square of the distance to another point.
Definition: hugin_math.h:135