]> Shamusworld >> Repos - architektonas/blob - src/base/infoarea.cpp
Bugfixes related to removing Snapper class.
[architektonas] / src / base / infoarea.cpp
1 // infoarea.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  06/01/2010  Added this text. :-)
15 //
16
17 #include "infoarea.h"
18
19 #include "mathextra.h"
20 #include "debug.h"
21
22 /**
23  * Constructor.
24  */
25 InfoArea::InfoArea()
26 {
27 }
28
29 /**
30  * Destructor.
31  */
32 InfoArea::~InfoArea()
33 {
34 }
35
36 /**
37  * Adds a point to the internal list
38  *
39  * @param p co-ordinate of the point
40  */
41 void InfoArea::addPoint(const Vector & p)
42 {
43         if (thePoints.empty())
44                 baseY = p.y;
45
46         thePoints.append(p);
47 }
48
49 /**
50  * Resets the points.
51  */
52 void InfoArea::reset()
53 {
54         thePoints.clear();
55         area = 0.0;
56         circumference = 0.0;
57 }
58
59 /**
60  * Closes the polygon if it is not closed already.
61  */
62 void InfoArea::close()
63 {
64         if (isValid() && isClosed() == false)
65         {
66                 thePoints.append(thePoints.first());
67
68                 DEBUG->print("InfoArea::close: closed");
69         }
70 }
71
72 /**
73  * @retval true If the area is closed (i.e. start point and end point are
74  *   identical)
75  * @retval false Otherwise.
76  */
77 bool InfoArea::isClosed()
78 {
79         return (thePoints.first().distanceTo(thePoints.last()) < 1.0e-4);
80 }
81
82 /**
83  * @retval true If the area is defined (i.e. there are at least 3 points)
84  * @retval false If there are only two or less points.
85  */
86 bool InfoArea::isValid()
87 {
88         DEBUG->print("InfoArea::isValid: count: %d", thePoints.count());
89         return (thePoints.count() > 2);
90 }
91
92 /**
93  * Calculates the area and the circumference of the area.
94  */
95 void InfoArea::calculate()
96 {
97         area = 0.0;
98         circumference = 0.0;
99         Vector ptFirst;
100         Vector p1;
101         Vector p2;
102
103         // at least 3 points needed for an area
104         if (isValid())
105         {
106                 ptFirst = thePoints.last();
107                 thePoints.pop_back();
108
109                 p1 = ptFirst;
110
111                 while (!thePoints.empty())
112                 {
113                         p2 = thePoints.last();
114                         thePoints.pop_back();
115
116                         area += calcSubArea(p1, p2);
117                         circumference += p1.distanceTo(p2);
118                         //if (p1 != ptFirst) {
119                         //      delete p1;
120                         //}
121                         p1 = p2;
122                 }
123
124                 area += calcSubArea(p1, ptFirst);
125                 circumference += p1.distanceTo(ptFirst);
126                 //delete p1;
127                 //delete ptFirst;
128         }
129
130         //thePoints.clear();
131         area = fabs(area);
132 }
133
134 double InfoArea::getArea()
135 {
136         return area;
137 }
138
139 double InfoArea::getCircumference()
140 {
141         return circumference;
142 }
143
144 int InfoArea::count()
145 {
146         return thePoints.count();
147 }
148
149 /**
150  * Calculates a sub area.
151  *
152  * @param p1 first point
153  * @param p2 second point
154  */
155 double InfoArea::calcSubArea(const Vector & p1, const Vector & p2)
156 {
157         double width = p2.x - p1.x;
158         double height = (p1.y - baseY) + (p2.y - baseY);
159
160         return (width * height) / 2.0;
161 }
162
163 /*! Calculates a distance
164     \param _p1 first point
165     \param _p2 second point
166 */
167 /*double
168 InfoArea::calcDistance(Vector *_p1, Vector *_p2)
169 {
170         return mtGetDistance(_p1->getX(), _p1->getY(), _p2->getX(), _p2->getY());
171 }*/