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