]> Shamusworld >> Repos - architektonas/blob - src/object.cpp
Added new triangulation tool, ability to snap to endpoints/intersections.
[architektonas] / src / object.cpp
1 //
2 // object.cpp: Base class for all CAD objects
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // WHO  WHEN        WHAT
11 // ---  ----------  ------------------------------------------------------------
12 // JLH  03/22/2011  Created this file
13 // JLH  04/01/2011  Added constructor to allow derived objects to have empty
14 //                  constructor bodies, added state querying
15 // JLH  04/02/2001  Added static methods for global states (fixed angle, etc)
16 //
17
18 #include "object.h"
19 #include <stdlib.h>
20 #include <math.h>
21
22 // Initialize static variables
23 bool Object::fixedAngle = false;
24 bool Object::fixedLength = false;
25 QFont * Object::font = 0;
26 int Object::viewportHeight = 0;
27 bool Object::deleteActive = false;
28 bool Object::dimensionActive = false;
29 bool Object::snapToGrid = true;
30 //snapToPoints all well here?
31 bool Object::ignoreClicks = false;
32 bool Object::dontMove = false;
33 bool Object::selectionInProgress = false;
34 QRectF Object::selection;
35 double Object::gridSpacing;
36 int Object::currentLayer = 0;
37 Point Object::snapPoint;
38 bool Object::snapPointIsValid = false;
39
40
41 Object::Object(): position(Vector(0, 0)), parent(0), type(OTObject),
42         state(OSInactive), layer(0), oldState(OSInactive), needUpdate(false)
43         //, attachedDimension(0)
44 {
45 }
46
47
48 Object::Object(Vector v,  Object * passedInParent/*= 0*/): position(v),
49         parent(passedInParent), state(OSInactive), layer(0), oldState(OSInactive),
50         needUpdate(false)//, attachedDimension(0)
51 {
52 }
53
54
55 Object::~Object()
56 {
57 printf("Object: Destroyed!\n");
58         for(uint i=0; i<connected.size(); i++)
59                 connected[i].object->DisconnectAll(this);
60 }
61
62
63 /*virtual*/ void Object::Draw(Painter *)
64 {
65 }
66
67
68 /*virtual*/ Vector Object::Center(void)
69 {
70         return Vector();
71 }
72
73
74 /*virtual*/ bool Object::Collided(Vector)
75 {
76         return false;
77 }
78
79
80 /*virtual*/ bool Object::PointerMoved(Vector)
81 {
82         return false;
83 }
84
85
86 /*virtual*/ void Object::PointerReleased(void)
87 {
88 }
89
90
91 /*virtual*/ bool Object::NeedsUpdate(void)
92 {
93         return needUpdate;
94 }
95
96
97 /*virtual*/ bool Object::HitTest(Point)
98 {
99         return false;
100 }
101
102
103 // This is intended to be overridden by the Container class, for object morphing
104 /*virtual*/ void Object::Transmute(Object *, Object *)
105 {
106 }
107
108
109 /*virtual*/ Object * Object::GetParent(void)
110 {
111         return parent;
112 }
113
114
115 /*virtual*/ void Object::Add(Object *)
116 {
117 }
118
119
120 // This returns a pointer to the point passed in, if it coincides. Otherwise returns NULL.
121 /*virtual*/ Vector * Object::GetPointAt(Vector)
122 {
123         return 0;
124 }
125
126
127 // This is meant for writing object data to a file.
128 /*virtual*/ void Object::Enumerate(FILE *)
129 {
130 }
131
132
133 /*virtual*/ Object * Object::Copy(void)
134 {
135         return new Object(position, parent);
136 }
137
138
139 // This returns a point on the object at 'parameter', which is between 0 and 1.
140 // Default is to return the object's position.
141 /*virtual*/ Vector Object::GetPointAtParameter(double)
142 {
143         return position;
144 }
145
146
147 // Since these functions are pretty much non-object specific, we can implement
148 // them here. :-)
149 /*virtual*/ void Object::Connect(Object * obj, double parameter)
150 {
151         // Check to see if this connection is already in our list...
152         Connection c(obj, parameter);
153         std::vector<Connection>::iterator i;
154
155         for(i=connected.begin(); i!=connected.end(); i++)
156         {
157                 // Bail out if this connection is already present...
158                 if (*i == c)
159                         return;
160         }
161
162         // Connection is a new one, add it in...
163         connected.push_back(c);
164 }
165
166
167 /*virtual*/ void Object::Disconnect(Object * obj, double parameter)
168 {
169         std::vector<Connection>::iterator i;
170
171         for(i=connected.begin(); i!=connected.end(); i++)
172         {
173                 if (((*i).object == obj) && ((*i).t == parameter))
174                 {
175                         connected.erase(i);
176                         return;
177                 }
178         }
179 }
180
181
182 /*virtual*/ void Object::DisconnectAll(Object * obj)
183 {
184         std::vector<Connection>::iterator i;
185
186         for(i=connected.begin(); i!=connected.end(); )
187         {
188                 if ((*i).object == obj)
189                         connected.erase(i);
190                 else
191                         i++;
192         }
193 }
194
195
196 /*virtual*/ QRectF Object::Extents(void)
197 {
198         // Generic object returns an empty rect...
199         return QRectF();
200 }
201
202
203 #if 0
204 /*virtual*/ ObjectType Object::Type(void)
205 {
206         return OTObject;
207 }
208 #endif
209
210
211 /*virtual*/ void Object::Translate(Vector amount)
212 {
213         position += amount;
214 }
215
216
217 /*virtual*/ void Object::Rotate(Point, double)
218 {
219 }
220
221
222 /*virtual*/ void Object::Scale(Point, double)
223 {
224 }
225
226
227 /*virtual*/ void Object::Mirror(Point, Point)
228 {
229 }
230
231
232 /*virtual*/ void Object::Save(void)
233 {
234         oldPosition = position;
235 }
236
237
238 /*virtual*/ void Object::Restore(void)
239 {
240         position = oldPosition;
241 }
242
243
244 ObjectState Object::GetState(void)
245 {
246         return state;
247 }
248
249
250 void Object::Reparent(Object * newParent)
251 {
252         parent = newParent;
253 }
254
255
256 /*Dimension * Object::GetAttachedDimension(void)
257 {
258         return attachedDimension;
259 }*/
260
261
262 // Class methods...
263
264 void Object::SetFixedAngle(bool state/*= true*/)
265 {
266         fixedAngle = state;
267 }
268
269
270 void Object::SetFixedLength(bool state/*= true*/)
271 {
272         fixedLength = state;
273 }
274
275
276 void Object::SetFont(QFont * f)
277 {
278         font = f;
279 }
280
281
282 void Object::SetViewportHeight(int height)
283 {
284         viewportHeight = height;
285 }
286
287
288 void Object::SetDeleteActive(bool state/*= true*/)
289 {
290         deleteActive = state;
291 }
292
293
294 void Object::SetDimensionActive(bool state/*= true*/)
295 {
296         dimensionActive = state;
297 }
298
299
300 void Object::SetSnapMode(bool state/*= true*/)
301 {
302         snapToGrid = state;
303 }
304
305
306 //
307 // This looks strange, but it's really quite simple: We want a point that's
308 // more than half-way to the next grid point to snap there while conversely we
309 // want a point that's less than half-way to to the next grid point then snap
310 // to the one before it. So we add half of the grid spacing to the point, then
311 // divide by it so that we can remove the fractional part, then multiply it
312 // back to get back to the correct answer.
313 //
314 Vector Object::SnapPointToGrid(Vector point)
315 {
316         point += gridSpacing / 2.0;             // *This* adds to Z!!!
317         point /= gridSpacing;
318         point.x = floor(point.x);//need to fix this for negative numbers...
319         point.y = floor(point.y);
320         point.z = 0;                                    // Make *sure* Z doesn't go anywhere!!!
321         point *= gridSpacing;
322         return point;
323 }
324
325