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