]> Shamusworld >> Repos - architektonas/blob - src/base/rs_solid.cpp
In the middle of major refactoring...
[architektonas] / src / base / rs_solid.cpp
1 // rs_solid.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/02/2010  Added this text. :-)
13 //
14
15 #include "rs_solid.h"
16
17 #include "graphicview.h"
18 #include "paintinterface.h"
19
20 /**
21  * Default constructor.
22  */
23 RS_Solid::RS_Solid(RS_EntityContainer * parent, const RS_SolidData & d):
24         RS_AtomicEntity(parent), data(d)
25 {
26         calculateBorders();
27 }
28
29 /*virtual*/ RS_Entity * RS_Solid::clone()
30 {
31         RS_Solid * s = new RS_Solid(*this);
32         s->initId();
33         return s;
34 }
35
36 /**     @return RS_ENTITY_POINT */
37 /*virtual*/ RS2::EntityType RS_Solid::rtti() const
38 {
39         return RS2::EntitySolid;
40 }
41
42 /**
43  * @return Start point of the entity.
44  */
45 /*virtual*/ Vector RS_Solid::getStartpoint() const
46 {
47         return Vector(false);
48 }
49
50 /**
51  * @return End point of the entity.
52  */
53 /*virtual*/ Vector RS_Solid::getEndpoint() const
54 {
55         return Vector(false);
56 }
57
58 /** @return Copy of data that defines the point. */
59 RS_SolidData RS_Solid::getData() const
60 {
61         return data;
62 }
63
64 /** @return true if this is a triangle. */
65 bool RS_Solid::isTriangle()
66 {
67         return !data.corner[3].valid;
68 }
69
70 /**
71  * @return Corner number 'num'.
72  */
73 Vector RS_Solid::getCorner(int num)
74 {
75         if (num >= 0 && num < 4)
76                 return data.corner[num];
77         else
78         {
79                 RS_DEBUG->print("Illegal corner requested from Solid", RS_Debug::D_WARNING);
80                 return Vector(false);
81         }
82 }
83
84 /**
85  * Shapes this Solid into a standard arrow (used in dimensions).
86  *
87  * @param point The point the arrow points to.
88  * @param angle Direction of the arrow.
89  * @param arrowSize Size of arrow (length).
90  */
91 void RS_Solid::shapeArrow(const Vector & point, double angle, double arrowSize)
92 {
93         double cosv1, sinv1, cosv2, sinv2;
94         double arrowSide = arrowSize / cos(0.165);
95
96         cosv1 = cos(angle + 0.165) * arrowSide;
97         sinv1 = sin(angle + 0.165) * arrowSide;
98         cosv2 = cos(angle - 0.165) * arrowSide;
99         sinv2 = sin(angle - 0.165) * arrowSide;
100
101         data.corner[0] = point;
102         data.corner[1] = Vector(point.x - cosv1, point.y - sinv1);
103         data.corner[2] = Vector(point.x - cosv2, point.y - sinv2);
104         data.corner[3] = Vector(false);
105
106         calculateBorders();
107 }
108
109 void RS_Solid::calculateBorders()
110 {
111         resetBorders();
112
113         for(int i=0; i<4; ++i)
114         {
115                 if (data.corner[i].valid)
116                 {
117                         minV = Vector::minimum(minV, data.corner[i]);
118                         maxV = Vector::maximum(maxV, data.corner[i]);
119                 }
120         }
121 }
122
123 Vector RS_Solid::getNearestEndpoint(const Vector & coord, double * dist)
124 {
125         double minDist = RS_MAXDOUBLE;
126         double curDist;
127         Vector ret;
128
129         for(int i=0; i<4; ++i)
130         {
131                 if (data.corner[i].valid)
132                 {
133                         curDist = data.corner[i].distanceTo(coord);
134
135                         if (curDist < minDist)
136                         {
137                                 ret = data.corner[i];
138                                 minDist = curDist;
139                         }
140                 }
141         }
142
143         if (dist)
144                 *dist = minDist;
145
146         return ret;
147 }
148
149 /**
150  * @todo Implement this.
151  */
152 Vector RS_Solid::getNearestPointOnEntity(const Vector & /*coord*/, bool /*onEntity*/,
153         double * /*dist*/, RS_Entity ** /*entity*/)
154 {
155         Vector ret(false);
156         return ret;
157 }
158
159 Vector RS_Solid::getNearestCenter(const Vector & /*coord*/, double * dist)
160 {
161         if (dist)
162                 *dist = RS_MAXDOUBLE;
163
164         return Vector(false);
165 }
166
167 Vector RS_Solid::getNearestMiddle(const Vector & /*coord*/, double * dist)
168 {
169         if (dist)
170                 *dist = RS_MAXDOUBLE;
171
172         return Vector(false);
173 }
174
175 Vector RS_Solid::getNearestDist(double /*distance*/, const Vector & /*coord*/, double * dist)
176 {
177         if (dist)
178                 *dist = RS_MAXDOUBLE;
179
180         return Vector(false);
181 }
182
183 /**
184  * @return Distance from one of the boundry lines of this solid to given point.
185  *
186  * @todo implement
187  */
188 double RS_Solid::getDistanceToPoint(const Vector & /*coord*/, RS_Entity ** /*entity*/,
189         RS2::ResolveLevel /*level*/, double /*solidDist*/)
190 {
191         return RS_MAXDOUBLE;
192 }
193
194 void RS_Solid::move(Vector offset)
195 {
196         for(int i=0; i<4; ++i)
197                 data.corner[i].move(offset);
198
199         calculateBorders();
200 }
201
202 void RS_Solid::rotate(Vector center, double angle)
203 {
204         for(int i=0; i<4; ++i)
205                 data.corner[i].rotate(center, angle);
206
207         calculateBorders();
208 }
209
210 void RS_Solid::scale(Vector center, Vector factor)
211 {
212         for(int i=0; i<4; ++i)
213                 data.corner[i].scale(center, factor);
214
215         calculateBorders();
216 }
217
218 void RS_Solid::mirror(Vector axisPoint1, Vector axisPoint2)
219 {
220         for(int i=0; i<4; ++i)
221                 data.corner[i].mirror(axisPoint1, axisPoint2);
222
223         calculateBorders();
224 }
225
226 void RS_Solid::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
227 {
228         if (!painter || !view)
229                 return;
230
231         RS_SolidData d = getData();
232
233         if (isTriangle())
234                 painter->fillTriangle(view->toGui(getCorner(0)), view->toGui(getCorner(1)),
235                         view->toGui(getCorner(2)));
236 }
237
238 /**
239  * Dumps the point's data to stdout.
240  */
241 std::ostream & operator<<(std::ostream & os, const RS_Solid & p)
242 {
243         os << " Solid: " << p.getData() << "\n";
244         return os;
245 }