]> Shamusworld >> Repos - architektonas/blob - src/base/rs_infoarea.cpp
Initial import
[architektonas] / src / base / rs_infoarea.cpp
1 /****************************************************************************
2 ** $Id: rs_infoarea.cpp 1892 2004-07-09 23:54:59Z andrew $
3 **
4 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
5 **
6 ** This file is part of the qcadlib Library project.
7 **
8 ** This file may be distributed and/or modified under the terms of the
9 ** GNU General Public License version 2 as published by the Free Software
10 ** Foundation and appearing in the file LICENSE.GPL included in the
11 ** packaging of this file.
12 **
13 ** Licensees holding valid qcadlib Professional Edition licenses may use
14 ** this file in accordance with the qcadlib Commercial License
15 ** Agreement provided with the Software.
16 **
17 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 **
20 ** See http://www.ribbonsoft.com for further details.
21 **
22 ** Contact info@ribbonsoft.com if any conditions of this licensing are
23 ** not clear to you.
24 **
25 **********************************************************************/
26
27 #include "rs_infoarea.h"
28
29 #include "rs_math.h"
30 #include "rs_debug.h"
31
32 /**
33  * Constructor.
34  */
35 RS_InfoArea::RS_InfoArea()
36 {
37 }
38
39 /**
40  * Destructor.
41  */
42 RS_InfoArea::~RS_InfoArea()
43 {
44 }
45
46 /**
47  * Adds a point to the internal list
48  *
49  * @param p co-ordinate of the point
50  */
51 void RS_InfoArea::addPoint(const Vector & p)
52 {
53         if (thePoints.empty())
54                 baseY = p.y;
55
56         thePoints.append(p);
57 }
58
59 /**
60  * Resets the points.
61  */
62 void RS_InfoArea::reset()
63 {
64         thePoints.clear();
65         area = 0.0;
66         circumference = 0.0;
67 }
68
69 /**
70  * Closes the polygon if it is not closed already.
71  */
72 void RS_InfoArea::close()
73 {
74         if (isValid() && isClosed() == false)
75         {
76                 thePoints.append(thePoints.first());
77
78                 RS_DEBUG->print("RS_InfoArea::close: closed");
79         }
80 }
81
82 /**
83  * @retval true If the area is closed (i.e. start point and end point are
84  *   identical)
85  * @retval false Otherwise.
86  */
87 bool RS_InfoArea::isClosed()
88 {
89         return (thePoints.first().distanceTo(thePoints.last()) < 1.0e-4);
90 }
91
92 /**
93  * @retval true If the area is defined (i.e. there are at least 3 points)
94  * @retval false If there are only two or less points.
95  */
96 bool RS_InfoArea::isValid()
97 {
98         RS_DEBUG->print("RS_InfoArea::isValid: count: %d", thePoints.count());
99         return (thePoints.count() > 2);
100 }
101
102 /**
103  * Calculates the area and the circumference of the area.
104  */
105 void RS_InfoArea::calculate()
106 {
107         area = 0.0;
108         circumference = 0.0;
109         Vector ptFirst;
110         Vector p1;
111         Vector p2;
112
113         // at least 3 points needed for an area
114         if (isValid())
115         {
116                 ptFirst = thePoints.last();
117                 thePoints.pop_back();
118
119                 p1 = ptFirst;
120
121                 while (!thePoints.empty())
122                 {
123                         p2 = thePoints.last();
124                         thePoints.pop_back();
125
126                         area += calcSubArea(p1, p2);
127                         circumference += p1.distanceTo(p2);
128                         //if (p1 != ptFirst) {
129                         //      delete p1;
130                         //}
131                         p1 = p2;
132                 }
133
134                 area += calcSubArea(p1, ptFirst);
135                 circumference += p1.distanceTo(ptFirst);
136                 //delete p1;
137                 //delete ptFirst;
138         }
139
140         //thePoints.clear();
141         area = fabs(area);
142 }
143
144 double RS_InfoArea::getArea()
145 {
146         return area;
147 }
148
149 double RS_InfoArea::getCircumference()
150 {
151         return circumference;
152 }
153
154 int RS_InfoArea::count()
155 {
156         return thePoints.count();
157 }
158
159 /**
160  * Calculates a sub area.
161  *
162  * @param p1 first point
163  * @param p2 second point
164  */
165 double RS_InfoArea::calcSubArea(const Vector & p1, const Vector & p2)
166 {
167         double width = p2.x - p1.x;
168         double height = (p1.y - baseY) + (p2.y - baseY);
169
170         return (width * height) / 2.0;
171 }
172
173 /*! Calculates a distance
174     \param _p1 first point
175     \param _p2 second point
176 */
177 /*double
178 RS_InfoArea::calcDistance(Vector *_p1, Vector *_p2)
179 {
180         return mtGetDistance(_p1->getX(), _p1->getY(), _p2->getX(), _p2->getY());
181 }*/