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