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 void MaskPolygon::removePoint(const unsigned int index)
125 {
126  if(index<m_polygon.size())
127  {
128  m_polygon.erase(m_polygon.begin()+index);
129  calcBoundingBox();
130  };
131 };
132 
133 void MaskPolygon::movePointTo(const unsigned int index, const hugin_utils::FDiff2D p)
134 {
135  if(index<m_polygon.size())
136  {
137  m_polygon[index] = p;
138  calcBoundingBox();
139  };
140 };
141 
142 void MaskPolygon::movePointBy(const unsigned int index, const hugin_utils::FDiff2D diff)
143 {
144  if(index<m_polygon.size())
145  {
146  m_polygon[index] += diff;
147  calcBoundingBox();
148  };
149 };
150 
151 void MaskPolygon::scale(const double factorx,const double factory)
152 {
153  for(unsigned int i=0;i<m_polygon.size();i++)
154  {
155  m_polygon[i].x*=factorx;
156  m_polygon[i].y*=factory;
157  };
158  calcBoundingBox();
159 };
160 
161 void MaskPolygon::scale(const double factor, const hugin_utils::FDiff2D& p)
162 {
163  for (unsigned int i = 0; i < m_polygon.size(); i++)
164  {
165  m_polygon[i] = (m_polygon[i] - p) * factor + p;
166  };
167  calcBoundingBox();
168 }
169 
171 {
172  double xnew,ynew;
173  VectorPolygon newPoly;
174  for(unsigned int i=0;i<m_polygon.size();i++)
175  {
176  if(trans.transformImgCoord(xnew,ynew,m_polygon[i].x,m_polygon[i].y))
177  {
178  newPoly.push_back(hugin_utils::FDiff2D(xnew,ynew));
179  };
180  };
181  m_polygon=newPoly;
182  calcBoundingBox();
183 };
184 
185 void MaskPolygon::subSample(const double max_distance)
186 {
187  if(m_polygon.size()<3)
188  return;
189  VectorPolygon oldPoly=m_polygon;
190  unsigned int count=oldPoly.size();
191  m_polygon.clear();
192  for(unsigned int i=0;i<count;i++)
193  {
194  addPoint(oldPoly[i]);
195  hugin_utils::FDiff2D p1=oldPoly[i];
196  hugin_utils::FDiff2D p2=oldPoly[(i+1)%count];
197  double distance=norm(p2-p1);
198  if(distance>max_distance)
199  {
200  //add intermediate points
201  double currentDistance=max_distance;
202  while(currentDistance<distance)
203  {
204  hugin_utils::FDiff2D p_new=p1+(p2-p1)*currentDistance/distance;
205  addPoint(p_new);
206  currentDistance+=max_distance;
207  };
208  };
209  };
210 };
211 
213 {
214  if(!m_polygon.empty())
215  {
216  m_boundingBox = vigra::Rect2D(vigra::Point2D(m_polygon[0].x, m_polygon[0].y), vigra::Size2D(1, 1));
217  if(m_polygon.size()>1)
218  {
219  for(unsigned int i=1;i<m_polygon.size();i++)
220  {
221  m_boundingBox|=vigra::Point2D(m_polygon[i].x,m_polygon[i].y);
222  };
223  };
224  //adding a small border to get no rounding error because polygon coordinates are float
225  //numbers, but bounding box has integer coordinates
226  m_boundingBox.addBorder(2);
227  };
228 };
229 
230 //helper function for clipping
232 {
237 };
238 
239 bool clip_isSide(const hugin_utils::FDiff2D p, const vigra::Rect2D r, const clipSide side)
240 {
241  switch(side){
242  case clipLeft:
243  return p.x>=r.left();
244  case clipRight:
245  return p.x<=r.right();
246  case clipTop:
247  return p.y>=r.top();
248  case clipBottom:
249  return p.y<=r.bottom();
250  };
251  //this should never happens
252  return false;
253 }
254 
256 {
257  double a;
258  double b;
259  double xnew;
260  double ynew;
261  if(q.x-p.x==0)
262  {
263  a=0;
264  b=p.y;
265  }
266  else
267  {
268  a=(q.y-p.y)/(q.x-p.x);
269  b=p.y-p.x*a;
270  };
271  switch(side){
272  case clipLeft:
273  xnew=r.left();
274  ynew=xnew*a+b;
275  break;
276  case clipRight:
277  xnew=r.right();
278  ynew=xnew*a+b;
279  break;
280  case clipTop:
281  ynew=r.top();
282  if(a!=0)
283  xnew=(ynew-b)/a;
284  else
285  xnew=p.x;
286  break;
287  case clipBottom:
288  ynew=r.bottom();
289  if(a!=0)
290  xnew=(ynew-b)/a;
291  else
292  xnew=p.x;
293  break;
294  };
295  return hugin_utils::FDiff2D(xnew,ynew);
296 };
297 
298 VectorPolygon clip_onPlane(const VectorPolygon& polygon, const vigra::Rect2D r, const clipSide side)
299 {
300  if(polygon.size()<3)
301  {
302  return polygon;
303  };
304  hugin_utils::FDiff2D s=polygon[polygon.size()-1];
306  VectorPolygon newPolygon;
307  for(unsigned int i=0;i<polygon.size();i++)
308  {
309  p=polygon[i];
310  if(clip_isSide(p,r,side))
311  {
312  // point p is "inside"
313  if(!clip_isSide(s,r,side))
314  // and point s is "outside"
315  newPolygon.push_back(clip_getIntersection(p,s,r,side));
316  newPolygon.push_back(p);
317  }
318  else
319  {
320  //point p is "outside"
321  if(clip_isSide(s,r,side))
322  //ans point s is "inside"
323  newPolygon.push_back(clip_getIntersection(s,p,r,side));
324  };
325  s=p;
326  };
327  return newPolygon;
328 };
329 
330 bool MaskPolygon::clipPolygon(const vigra::Rect2D rect)
331 {
332  //clipping using Sutherland-Hodgman algorithm
337  calcBoundingBox();
338  return (m_polygon.size()>2);
339 };
340 
341 //helper function for clipping
348 bool clip_insideCircle(const hugin_utils::FDiff2D p, const hugin_utils::FDiff2D center, const double radius)
349 {
350  return p.squareDistance(center)<=radius*radius;
351 };
352 
360 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)
361 {
362  std::vector<hugin_utils::FDiff2D> intersections;
363  hugin_utils::FDiff2D slope=s-p;
364  if(slope.squareLength()<1e-5)
365  {
366  return intersections;
367  };
368  hugin_utils::FDiff2D p2=p-center;
369  double dotproduct=p2.x*slope.x+p2.y*slope.y;
370  double root=sqrt(dotproduct*dotproduct-slope.squareLength()*(p2.squareLength()-radius*radius));
371  double t1=(-dotproduct+root)/slope.squareLength();
372  double t2=(-dotproduct-root)/slope.squareLength();
373  std::set<double> t;
374  if(t1>0 && t1<1)
375  {
376  t.insert(t1);
377  };
378  if(t2>0 && t2<1)
379  {
380  if(fabs(t2-t1)>1e-5)
381  {
382  t.insert(t2);
383  };
384  };
385  if(!t.empty())
386  {
387  for(std::set<double>::const_iterator it=t.begin();it!=t.end();++it)
388  {
389  intersections.push_back(p+slope*(*it));
390  };
391  };
392  return intersections;
393 };
394 
397 {
398  return asin((a.x*b.y-a.y*b.x)/(sqrt(a.squareLength())*sqrt(b.squareLength())));
399 };
400 
408 void generateArc(VectorPolygon& poly, const hugin_utils::FDiff2D s, const hugin_utils::FDiff2D center, const double radius, const bool clockwise)
409 {
410  if(poly.empty())
411  {
412  return;
413  };
414  hugin_utils::FDiff2D p=poly[poly.size()-1];
415  double maxDistance=5.0;
416  if(p.squareDistance(s)<maxDistance*maxDistance)
417  {
418  return;
419  };
420  double angle=atan2(p.y-center.y,p.x-center.x);
421  double final_angle=atan2(s.y-center.y,s.x-center.x);
422  //step 1 degree or less, so that max distance between 2 points is smaller than maxDistance
423  double step=std::min<double>(PI/180,atan2(maxDistance,radius));
424  if(!clockwise)
425  {
426  while(final_angle<angle)
427  {
428  final_angle+=2*PI;
429  };
430  angle+=step;
431  while(angle<final_angle)
432  {
433  poly.push_back(hugin_utils::FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y));
434  angle+=step;
435  };
436  }
437  else
438  {
439  while(final_angle>angle)
440  {
441  final_angle-=2*PI;
442  };
443  angle-=step;
444  while(angle>final_angle)
445  {
446  poly.push_back(hugin_utils::FDiff2D(cos(angle)*radius+center.x,sin(angle)*radius+center.y));
447  angle-=step;
448  };
449  };
450 };
451 
452 bool MaskPolygon::clipPolygon(const hugin_utils::FDiff2D center,const double radius)
453 {
454  if(radius<=0 || m_polygon.size()<3)
455  {
456  return false;
457  };
459  bool s_inside=clip_insideCircle(s,center,radius);
461  VectorPolygon newPolygon;
462  bool needsFinalArc=false;
463  double angleCovered=0;
464  double angleCoveredOffset=0;
465  for(unsigned int i=0;i<m_polygon.size();i++)
466  {
467  p=m_polygon[i];
468  bool p_inside=clip_insideCircle(p,center,radius);
469  if(p_inside)
470  {
471  if(s_inside)
472  {
473  //both points inside
474  newPolygon.push_back(p);
475  }
476  else
477  {
478  //line crosses circles from outside
479  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(p,s,center,radius);
480  DEBUG_ASSERT(points.size()==1);
481  angleCovered+=angle_between(s-center,points[0]-center);
482  if(newPolygon.empty())
483  {
484  needsFinalArc=true;
485  angleCoveredOffset=angleCovered;
486  }
487  else
488  {
489  generateArc(newPolygon,points[0],center,radius,angleCovered<0);
490  };
491  newPolygon.push_back(points[0]);
492  newPolygon.push_back(p);
493  };
494  }
495  else
496  {
497  if(!s_inside)
498  {
499  //both points outside of circle
500  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
501  //intersection can only be zero points or 2 points
502  if(points.size()>1)
503  {
504  angleCovered+=angle_between(s-center,points[0]-center);
505  if(newPolygon.empty())
506  {
507  needsFinalArc=true;
508  angleCoveredOffset=angleCovered;
509  }
510  else
511  {
512  generateArc(newPolygon,points[0],center,radius,angleCovered<0);
513  };
514  newPolygon.push_back(points[0]);
515  newPolygon.push_back(points[1]);
516  angleCovered=angle_between(points[1]-center,p-center);
517  }
518  else
519  {
520  angleCovered+=angle_between(s-center,p-center);
521  };
522  }
523  else
524  {
525  //line segment intersects circle from inside
526  std::vector<hugin_utils::FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
527  angleCovered=0;
528  DEBUG_ASSERT(points.size()==1);
529  newPolygon.push_back(points[0]);
530  };
531  };
532  s=p;
533  s_inside=p_inside;
534  };
535  if(needsFinalArc && newPolygon.size()>1)
536  {
537  generateArc(newPolygon,newPolygon[0],center,radius,(angleCovered+angleCoveredOffset)<0);
538  };
539  m_polygon=newPolygon;
540  calcBoundingBox();
541  return (m_polygon.size()>2);
542 };
543 
544 void MaskPolygon::rotate90(bool clockwise,unsigned int maskWidth,unsigned int maskHeight)
545 {
546  for(unsigned int i=0;i<m_polygon.size();i++)
547  {
548  if(clockwise)
549  {
551  m_polygon[i].x=maskHeight-p.y;
552  m_polygon[i].y=p.x;
553  }
554  else
555  {
557  m_polygon[i].x=p.y;
558  m_polygon[i].y=maskWidth-p.x;
559  };
560  };
561  calcBoundingBox();
562 };
563 
564 unsigned int MaskPolygon::FindPointNearPos(const hugin_utils::FDiff2D p, const double tol) const
565 {
566  if(m_polygon.empty())
567  return UINT_MAX;
569  unsigned int j=m_polygon.size()-1;
571  for(unsigned int i=0;i<m_polygon.size();i++)
572  {
573  p1=m_polygon[i];
574  // find intersection of perpendicular through point p and line between point i and j
575  hugin_utils::FDiff2D diff=p2-p1;
576  if(norm(diff)<0.001)
577  continue;
578  double u=((p.x-p1.x)*(p2.x-p1.x)+(p.y-p1.y)*(p2.y-p1.y))/hugin_utils::sqr(norm(diff));
579  if((u>=0.1) && (u<=0.9))
580  {
581  // intersection is between p1 and p2
582  hugin_utils::FDiff2D footpoint=p1+diff*u;
583  // now check distance between intersection and p
584  if(norm(p-footpoint)<tol)
585  return i==0 ? j+1 : i;
586  };
587  j=i;
588  p2=p1;
589  };
590  return UINT_MAX;
591 };
592 
594 {
595  if (this == &otherPoly)
596  return *this;
597  setMaskType(otherPoly.getMaskType());
598  setMaskPolygon(otherPoly.getMaskPolygon());
599  setImgNr(otherPoly.getImgNr());
600  setInverted(otherPoly.isInverted());
601  return *this;
602 };
603 
604 const bool MaskPolygon::operator==(const MaskPolygon& otherPoly) const
605 {
606  return ((m_maskType == otherPoly.getMaskType()) && (m_polygon == otherPoly.getMaskPolygon()));
607 };
608 
609 bool MaskPolygon::parsePolygonString(const std::string& polygonStr)
610 {
611  m_polygon.clear();
612  if(polygonStr.length()==0)
613  return false;
614  std::stringstream is(polygonStr);
615  while(is.good())
616  {
617  double x;
618  if (is >> x)
619  {
620  double y;
621  if (is >> y)
622  {
623  m_polygon.push_back(hugin_utils::FDiff2D(x, y));
624  };
625  };
626  };
627  calcBoundingBox();
628  return m_polygon.size()>2;
629 };
630 
631 void MaskPolygon::printPolygonLine(std::ostream &o, const unsigned int newImgNr) const
632 {
633  o<<"k i"<<newImgNr<<" ";
634  o<<"t"<<(int)m_maskType<<" ";
635  o<<"p\"";
636  for(unsigned int i=0; i<m_polygon.size(); i++)
637  {
638  o<<m_polygon[i].x<<" "<<m_polygon[i].y;
639  if((i+1)!=m_polygon.size())
640  o<<" ";
641  };
642  o<<"\""<<std::endl;
643 };
644 
646 {
647  if (m_polygon.empty())
648  {
649  return hugin_utils::FDiff2D();
650  }
651  else
652  {
653  hugin_utils::FDiff2D center;
654  for (size_t i = 0; i < m_polygon.size(); ++i)
655  {
656  center += m_polygon[i];
657  }
658  return center / (double)m_polygon.size();
659  };
660 }
661 
662 void LoadMaskFromStream(std::istream& stream,vigra::Size2D& imageSize, MaskPolygonVector &newMasks, size_t imgNr)
663 {
664  while (stream.good())
665  {
666  std::string line;
667  std::getline(stream,line);
668  switch (line[0])
669  {
670  case '#':
671  {
672  unsigned int w;
673  if (PTScriptParsing::getIntParam(w, line, "w"))
674  imageSize.setWidth(w);
675  unsigned int h;
676  if (PTScriptParsing::getIntParam(h, line, "h"))
677  imageSize.setHeight(h);
678  break;
679  }
680  case 'k':
681  {
682  HuginBase::MaskPolygon newPolygon;
683  //Ignore image number set in mask
684  newPolygon.setImgNr(imgNr);
685  unsigned int param;
686  if (PTScriptParsing::getIntParam(param,line,"t"))
687  {
689  }
690  std::string format;
691  if (PTScriptParsing::getPTParam(format,line,"p"))
692  {
693  if(newPolygon.parsePolygonString(format)) {
694  newMasks.push_back(newPolygon);
695  }
696  }
697  break;
698  }
699  default:
700  {
701  break;
702  }
703  }
704  }
705 };
706 
707 void SaveMaskToStream(std::ostream& stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
708 {
709  stream << "# w" << imageSize.width() << " h" << imageSize.height() << std::endl;
710  maskToWrite.printPolygonLine(stream, imgNr);
711 };
712 
713 } // namespace
void SaveMaskToStream(std::ostream &stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
save the mask into stream
Definition: Mask.cpp:707
double norm(T t)
Definition: hugin_math.h:187
hugin_utils::FDiff2D getCenter() const
return the center point of the polygon
Definition: Mask.cpp:645
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:124
bool parsePolygonString(const std::string &polygonStr)
parses the x and y positions from the given string
Definition: Mask.cpp:609
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:142
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:360
void LoadMaskFromStream(std::istream &stream, vigra::Size2D &imageSize, MaskPolygonVector &newMasks, size_t imgNr)
load the mask from stream
Definition: Mask.cpp:662
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:348
VectorPolygon clip_onPlane(const VectorPolygon &polygon, const vigra::Rect2D r, const clipSide side)
Definition: Mask.cpp:298
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:631
T sqr(T t)
Definition: hugin_math.h:181
#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:212
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:408
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:147
MaskType m_maskType
Definition: Mask.h:143
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:170
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:396
const bool operator==(const MaskPolygon &otherPoly) const
comparision operator
Definition: Mask.cpp:604
bool clip_isSide(const hugin_utils::FDiff2D p, const vigra::Rect2D r, const clipSide side)
Definition: Mask.cpp:239
VectorPolygon m_polygon
Definition: Mask.h:144
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:330
MaskPolygon & operator=(const MaskPolygon &otherPoly)
assign operator
Definition: Mask.cpp:593
TDiff2D< double > FDiff2D
Definition: hugin_math.h:162
std::vector< MaskPolygon > MaskPolygonVector
Definition: Mask.h:150
T squareLength() const
Return the square of the length of the vector.
Definition: hugin_math.h:153
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:255
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:133
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:185
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:564
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:544
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:151
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:147