2 // utils.cpp: Stuff that's useful to have kicking around, in one spot
4 // Part of the Architektonas Project
5 // (C) 2020 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
8 // JLH = James Hammons <jlhamm@acm.org>
11 // --- ---------- ------------------------------------------------------------
12 // JLH 05/01/2015 Created this file
17 #include <string.h> // For memcpy()
21 // Copy objects in one vector to another, creating copies and placing them in
22 // the other vector. Clearing & etc. of vectors is responsibility of the caller!
24 void CopyObjects(VPVector & from, VPVector & to)
26 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
28 Object * obj = (Object *)(*i);
29 Object * newObject = CopyObject(obj);
30 to.push_back(newObject);
34 VPVector CopyObjects(VPVector & src)
38 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
40 Object * newObject = CopyObject2((Object *)(*i));
41 copy.push_back(newObject);
48 // Create a copy of the passed in object.
50 Object * CopyObject(Object * obj)
52 void * newObject = NULL;
57 newObject = new Line();
58 memcpy(newObject, obj, sizeof(Line));
61 newObject = new Circle();
62 memcpy(newObject, obj, sizeof(Circle));
65 newObject = new Ellipse();
66 memcpy(newObject, obj, sizeof(Ellipse));
69 newObject = new Arc();
70 memcpy(newObject, obj, sizeof(Arc));
73 newObject = new Dimension();
74 memcpy(newObject, obj, sizeof(Dimension));
77 newObject = new Polyline();
78 memcpy(newObject, obj, sizeof(Polyline));
79 ((Polyline *)newObject)->points = ((Polyline *)obj)->points;
82 newObject = new Spline();
83 memcpy(newObject, obj, sizeof(Spline));
86 newObject = new Text();
87 memcpy(newObject, obj, sizeof(Text));
88 ((Text *)newObject)->s = ((Text *)obj)->s;
91 newObject = new Container();
93 // memcpy(newObject, obj, sizeof(Line));
94 ((Container *)newObject)->p[0] = obj->p[0];
95 ((Container *)newObject)->p[1] = obj->p[1];
96 ((Container *)newObject)->layer = obj->layer;
97 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
104 if (newObject && (((Object *)newObject)->type != OTContainer))
105 ((Object *)newObject)->id = Global::objectID++;
107 return (Object *)newObject;
111 // Create a copy of the passed in object. This version calls the second
112 // version of CopyObjects() (with one parameter and a vector return value).
114 Object * CopyObject2(Object * obj)
116 void * newObject = NULL;
121 newObject = new Line();
122 memcpy(newObject, obj, sizeof(Line));
126 newObject = new Circle();
127 memcpy(newObject, obj, sizeof(Circle));
131 newObject = new Ellipse();
132 memcpy(newObject, obj, sizeof(Ellipse));
136 newObject = new Arc();
137 memcpy(newObject, obj, sizeof(Arc));
141 newObject = new Dimension();
142 memcpy(newObject, obj, sizeof(Dimension));
146 newObject = new Polyline();
147 memcpy(newObject, obj, sizeof(Polyline));
148 ((Polyline *)newObject)->points = ((Polyline *)obj)->points;
152 newObject = new Spline();
153 memcpy(newObject, obj, sizeof(Spline));
157 newObject = new Text();
158 memcpy(newObject, obj, sizeof(Text));
159 ((Text *)newObject)->s = ((Text *)obj)->s;
163 newObject = new Container();
164 ((Container *)newObject)->p[0] = obj->p[0];
165 ((Container *)newObject)->p[1] = obj->p[1];
166 ((Container *)newObject)->layer = obj->layer;
167 ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
172 if (newObject && (((Object *)newObject)->type != OTContainer))
173 ((Object *)newObject)->id = Global::objectID++;
175 return (Object *)newObject;
178 void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
180 VPVectorIter i = from.begin();
182 while (i != from.end())
184 Object * obj = (Object *)(*i);
196 VPVector MoveSelectedObjectsFrom(VPVector & from)
199 VPVectorIter i = from.begin();
201 while (i != from.end())
203 Object * obj = (Object *)(*i);
207 objects.push_back(*i);
217 //hmm, this won't work, as these are just pointers...
219 void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
221 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
223 Object * obj = (Object *)(*i);
226 dest.push_back(CopyObject2(obj));
230 VPVector CopySelectedObjects(VPVector & src)
234 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
236 Object * obj = (Object *)(*i);
239 copy.push_back(CopyObject2(obj));
245 void AddObjectsTo(VPVector & dest, VPVector & from)
247 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
251 void ClearSelected(VPVector & v)
253 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
254 ((Object *)(*i))->selected = false;
258 // Select all *visible* objects. If an object's layer is invisible, skip it.
260 void SelectAll(VPVector & v)
262 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
264 Object * obj = (Object *)(*i);
265 bool visible = !Global::layerHidden[obj->layer];
266 obj->selected = visible;
271 // Recursively go down thru the Container's vectors, deleting all the objects
272 // contained therein. Once that is done, the main Container can be deleted.
273 // We don't have to worry about the underlying std::vectors, as they have their
274 // own destructors--plus they don't take ownership of objects, which is why we
275 // have to keep track of that stuff ourselves. :-P Believe it or not, this is
276 // a Good Thing(TM). ;-)
278 void DeleteContents(VPVector & v)
280 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
282 Object * obj = (Object *)(*i);
284 if (obj->type == OTContainer)
285 DeleteContents(((Container *)obj)->objects);
293 void DeleteSelectedObjects(VPVector & v)
295 VPVectorIter i = v.begin();
299 Object * obj = (Object *)(*i);
312 // This is used to remove selected objects from one container in order to move
313 // them to a different container.
315 void RemoveSelectedObjects(VPVector & v)
317 VPVectorIter i = v.begin();
321 Object * obj = (Object *)(*i);
331 // This is used to remove hovered objects from one container in order to delete
332 // them from the same container.
334 void RemoveHoveredObjects(VPVector & v)
336 VPVectorIter i = v.begin();
340 Object * obj = (Object *)(*i);
349 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
354 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
356 memcpy(&o, (Object *)(*i), sizeof(Object));
361 void RestorePointsTo(VPVector & v, std::vector<Object> & s)
363 std::vector<Object>::iterator i;
366 for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
368 Object * obj2 = (Object *)(*j);
369 obj2->p[0] = (*i).p[0];
370 obj2->p[1] = (*i).p[1];
371 obj2->angle[0] = (*i).angle[0];
372 obj2->angle[1] = (*i).angle[1];
373 //we don't do this because we want to keep selected & friends from changing
374 // memcpy(obj2, *j, sizeof(Object));
378 void RestorePointsTo(VPVector & v, VPVector & s)
380 for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
382 Object * objS = (Object *)(*i);
383 Object * objV = (Object *)(*j);
385 if (objV->type == OTContainer)
387 RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
391 objV->p[0] = objS->p[0];
392 objV->p[1] = objS->p[1];
393 objV->angle[0] = objS->angle[0];
394 objV->angle[1] = objS->angle[1];
395 //we don't do this because we want to keep selected & friends from changing
396 // memcpy(obj2, *j, sizeof(Object));
401 // Translate a single object; it it's a Container, translate all its contents,
402 // including subcontainers.
404 void TranslateObject(Object * obj, Point delta)
406 if (obj->type == OTContainer)
408 Container * c = (Container *)obj;
410 for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
411 TranslateObject((Object *)*i, delta);
413 else if (obj->type == OTPolyline)
414 ((Polyline *)obj)->Translate(delta);
421 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.
423 void TranslateContainer(Container * c, Point point, Point delta)
425 if (c->clicked == NULL)
427 // TranslateObject((Object *)c, delta);
432 //printf("TranslateContainer: boop (%i)\n", i++);
433 //we can set this to "point" and it won't move...
434 //do it *this* way, and non-enumerated clicks will do the right thing
435 Point clickedPoint = point - delta;
437 switch (c->clicked->type)
440 if (c->clicked->hitPoint[0])
441 clickedPoint = c->clicked->p[0];
442 else if (c->clicked->hitPoint[1])
443 clickedPoint = c->clicked->p[1];
444 else if (c->clicked->hitObject)
445 //Weirdness: some lines get a midpoint, some don't...
446 clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
451 if (c->clicked->hitPoint[0])
452 clickedPoint = c->clicked->p[0];
453 // else if (c->clicked->hitObject)
454 // clickedPoint = point - delta;
459 if (c->clicked->hitPoint[0])
460 clickedPoint = c->clicked->p[0];
461 else if (c->clicked->hitPoint[1])
462 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
463 else if (c->clicked->hitPoint[2])
464 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]);
465 // else if (c->clicked->hitObject)
466 // clickedPoint = point - delta;
477 Point clickedDelta = point - clickedPoint;
478 TranslateObject((Object *)c, clickedDelta);
482 // Translate all objects in the passed in vector, including Containers and all
483 // the objects they contain.
485 void TranslateObjects(VPVector & v, Point delta)
487 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
489 Object * obj = (Object *)(*i);
493 if (obj->type == OTContainer)
495 Container * c = (Container *)obj;
496 TranslateObjects(c->objects, delta);
498 else if (obj->type == OTPolyline)
500 ((Polyline *)obj)->Translate(delta);
506 // This does not *copy* the objects, it simply flattens out the pointers in the
507 // Container and all sub-Containers.
509 VPVector Flatten(Container * src)
513 for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
516 Object * obj = (Object *)(*i);
518 // Recursively add objects to the flat vector, if necessary
519 if (obj->type == OTContainer)
521 VPVector sub = Flatten((Container *)obj);
522 flat.insert(flat.end(), sub.begin(), sub.end());
530 // This does not *copy* the objects, it simply flattens out the pointers in the
531 // vector and all sub-Containers in the vector.
533 VPVector Flatten(VPVector src)
537 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
540 Object * obj = (Object *)(*i);
542 // Recursively add objects to the flat vector, if necessary
543 if (obj->type == OTContainer)
545 VPVector sub = Flatten(((Container *)obj)->objects);
546 flat.insert(flat.end(), sub.begin(), sub.end());