1 // utils.cpp: Stuff that's useful to have kicking around, in one spot
3 // Part of the Architektonas Project
4 // (C) 2020 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 05/01/2015 Created this file
16 #include <string.h> // For memcpy()
20 // Copy objects in one vector to another, creating copies and placing them in
21 // the other vector. Clearing & etc. of vectors is responsibility of the caller!
23 void CopyObjects(VPVector & from, VPVector & to)
25 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
27 Object * obj = (Object *)(*i);
28 Object * newObject = CopyObject(obj);
29 to.push_back(newObject);
33 VPVector CopyObjects(VPVector & src)
37 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
39 Object * newObject = CopyObject2((Object *)(*i));
40 copy.push_back(newObject);
47 // Create a copy of the passed in object.
49 Object * CopyObject(Object * obj)
51 void * newObject = NULL;
56 newObject = new Line();
57 memcpy(newObject, obj, sizeof(Line));
60 newObject = new Circle();
61 memcpy(newObject, obj, sizeof(Circle));
64 newObject = new Ellipse();
65 memcpy(newObject, obj, sizeof(Ellipse));
68 newObject = new Arc();
69 memcpy(newObject, obj, sizeof(Arc));
72 newObject = new Dimension();
73 memcpy(newObject, obj, sizeof(Dimension));
76 newObject = new Spline();
77 memcpy(newObject, obj, sizeof(Spline));
80 newObject = new Text();
81 memcpy(newObject, obj, sizeof(Text));
82 ((Text *)newObject)->s = ((Text *)obj)->s;
85 newObject = new Container();
87 // memcpy(newObject, obj, sizeof(Line));
88 ((Container *)newObject)->p[0] = obj->p[0];
89 ((Container *)newObject)->p[1] = obj->p[1];
90 ((Container *)newObject)->layer = obj->layer;
91 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
98 if (newObject && (((Object *)newObject)->type != OTContainer))
99 ((Object *)newObject)->id = Global::objectID++;
101 return (Object *)newObject;
105 // Create a copy of the passed in object. This version calls the second
106 // version of CopyObjects() (with one parameter and a vector return value).
108 Object * CopyObject2(Object * obj)
110 void * newObject = NULL;
115 newObject = new Line();
116 memcpy(newObject, obj, sizeof(Line));
120 newObject = new Circle();
121 memcpy(newObject, obj, sizeof(Circle));
125 newObject = new Ellipse();
126 memcpy(newObject, obj, sizeof(Ellipse));
130 newObject = new Arc();
131 memcpy(newObject, obj, sizeof(Arc));
135 newObject = new Dimension();
136 memcpy(newObject, obj, sizeof(Dimension));
140 newObject = new Spline();
141 memcpy(newObject, obj, sizeof(Spline));
145 newObject = new Text();
146 memcpy(newObject, obj, sizeof(Text));
147 ((Text *)newObject)->s = ((Text *)obj)->s;
151 newObject = new Container();
152 ((Container *)newObject)->p[0] = obj->p[0];
153 ((Container *)newObject)->p[1] = obj->p[1];
154 ((Container *)newObject)->layer = obj->layer;
155 ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
160 if (newObject && (((Object *)newObject)->type != OTContainer))
161 ((Object *)newObject)->id = Global::objectID++;
163 return (Object *)newObject;
166 void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
168 VPVectorIter i = from.begin();
170 while (i != from.end())
172 Object * obj = (Object *)(*i);
184 VPVector MoveSelectedObjectsFrom(VPVector & from)
187 VPVectorIter i = from.begin();
189 while (i != from.end())
191 Object * obj = (Object *)(*i);
195 objects.push_back(*i);
205 //hmm, this won't work, as these are just pointers...
207 void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
209 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
211 Object * obj = (Object *)(*i);
214 dest.push_back(CopyObject2(obj));
218 VPVector CopySelectedObjects(VPVector & src)
222 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
224 Object * obj = (Object *)(*i);
227 copy.push_back(CopyObject2(obj));
233 void AddObjectsTo(VPVector & dest, VPVector & from)
235 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
239 void ClearSelected(VPVector & v)
241 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
242 ((Object *)(*i))->selected = false;
246 // Select all *visible* objects. If an object's layer is invisible, skip it.
248 void SelectAll(VPVector & v)
250 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
252 Object * obj = (Object *)(*i);
253 bool visible = !Global::layerHidden[obj->layer];
254 obj->selected = visible;
259 // Recursively go down thru the Container's vectors, deleting all the objects
260 // contained therein. Once that is done, the main Container can be deleted.
261 // We don't have to worry about the underlying std::vectors, as they have their
262 // own destructors--plus they don't take ownership of objects, which is why we
263 // have to keep track of that stuff ourselves. :-P Believe it or not, this is
264 // a Good Thing(TM). ;-)
266 void DeleteContents(VPVector & v)
268 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
270 Object * obj = (Object *)(*i);
272 if (obj->type == OTContainer)
273 DeleteContents(((Container *)obj)->objects);
281 void DeleteSelectedObjects(VPVector & v)
283 VPVectorIter i = v.begin();
287 Object * obj = (Object *)(*i);
300 // This is used to remove selected objects from one container in order to move
301 // them to a different container.
303 void RemoveSelectedObjects(VPVector & v)
305 VPVectorIter i = v.begin();
309 Object * obj = (Object *)(*i);
318 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
323 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
325 memcpy(&o, (Object *)(*i), sizeof(Object));
330 void RestorePointsTo(VPVector & v, std::vector<Object> & s)
332 std::vector<Object>::iterator i;
335 for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
337 Object * obj2 = (Object *)(*j);
338 obj2->p[0] = (*i).p[0];
339 obj2->p[1] = (*i).p[1];
340 obj2->angle[0] = (*i).angle[0];
341 obj2->angle[1] = (*i).angle[1];
342 //we don't do this because we want to keep selected & friends from changing
343 // memcpy(obj2, *j, sizeof(Object));
347 void RestorePointsTo(VPVector & v, VPVector & s)
349 for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
351 Object * objS = (Object *)(*i);
352 Object * objV = (Object *)(*j);
354 if (objV->type == OTContainer)
356 RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
360 objV->p[0] = objS->p[0];
361 objV->p[1] = objS->p[1];
362 objV->angle[0] = objS->angle[0];
363 objV->angle[1] = objS->angle[1];
364 //we don't do this because we want to keep selected & friends from changing
365 // memcpy(obj2, *j, sizeof(Object));
370 // Translate a single object; it it's a Container, translate all its contents,
371 // including subcontainers.
373 void TranslateObject(Object * obj, Point delta)
375 if (obj->type == OTContainer)
377 Container * c = (Container *)obj;
379 for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
380 TranslateObject((Object *)*i, delta);
388 So we need to make it so that we pick the container's point clicked on, and translate all the other parts *not* clicked on.
390 void TranslateContainer(Container * c, Point point, Point delta)
392 if (c->clicked == NULL)
394 // TranslateObject((Object *)c, delta);
399 //printf("TranslateContainer: boop (%i)\n", i++);
400 //we can set this to "point" and it won't move...
401 //do it *this* way, and non-enumerated clicks will do the right thing
402 Point clickedPoint = point - delta;
404 switch (c->clicked->type)
407 if (c->clicked->hitPoint[0])
408 clickedPoint = c->clicked->p[0];
409 else if (c->clicked->hitPoint[1])
410 clickedPoint = c->clicked->p[1];
411 else if (c->clicked->hitObject)
412 //Weirdness: some lines get a midpoint, some don't...
413 clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
418 if (c->clicked->hitPoint[0])
419 clickedPoint = c->clicked->p[0];
420 // else if (c->clicked->hitObject)
421 // clickedPoint = point - delta;
426 if (c->clicked->hitPoint[0])
427 clickedPoint = c->clicked->p[0];
428 else if (c->clicked->hitPoint[1])
429 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
430 else if (c->clicked->hitPoint[2])
431 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0] + c->clicked->angle[1]), sin(c->clicked->angle[0] + c->clicked->angle[1])) * c->clicked->radius[0]);
432 // else if (c->clicked->hitObject)
433 // clickedPoint = point - delta;
444 Point clickedDelta = point - clickedPoint;
445 TranslateObject((Object *)c, clickedDelta);
449 // Translate all objects in the passed in vector, including Containers and all
450 // the objects they contain.
452 void TranslateObjects(VPVector & v, Point delta)
454 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
456 Object * obj = (Object *)(*i);
460 if (obj->type == OTContainer)
462 Container * c = (Container *)obj;
463 TranslateObjects(c->objects, delta);
469 // This does not *copy* the objects, it simply flattens out the pointers in the
470 // Container and all sub-Containers.
472 VPVector Flatten(Container * src)
476 for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
479 Object * obj = (Object *)(*i);
481 // Recursively add objects to the flat vector, if necessary
482 if (obj->type == OTContainer)
484 VPVector sub = Flatten((Container *)obj);
485 flat.insert(flat.end(), sub.begin(), sub.end());
493 // This does not *copy* the objects, it simply flattens out the pointers in the
494 // vector and all sub-Containers in the vector.
496 VPVector Flatten(VPVector src)
500 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
503 Object * obj = (Object *)(*i);
505 // Recursively add objects to the flat vector, if necessary
506 if (obj->type == OTContainer)
508 VPVector sub = Flatten(((Container *)obj)->objects);
509 flat.insert(flat.end(), sub.begin(), sub.end());