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 Spline();
78 memcpy(newObject, obj, sizeof(Spline));
81 newObject = new Text();
82 memcpy(newObject, obj, sizeof(Text));
83 ((Text *)newObject)->s = ((Text *)obj)->s;
86 newObject = new Container();
88 // memcpy(newObject, obj, sizeof(Line));
89 ((Container *)newObject)->p[0] = obj->p[0];
90 ((Container *)newObject)->p[1] = obj->p[1];
91 ((Container *)newObject)->layer = obj->layer;
92 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
99 if (newObject && (((Object *)newObject)->type != OTContainer))
100 ((Object *)newObject)->id = Global::objectID++;
102 return (Object *)newObject;
106 // Create a copy of the passed in object. This version calls the second
107 // version of CopyObjects() (with one parameter and a vector return value).
109 Object * CopyObject2(Object * obj)
111 void * newObject = NULL;
116 newObject = new Line();
117 memcpy(newObject, obj, sizeof(Line));
121 newObject = new Circle();
122 memcpy(newObject, obj, sizeof(Circle));
126 newObject = new Ellipse();
127 memcpy(newObject, obj, sizeof(Ellipse));
131 newObject = new Arc();
132 memcpy(newObject, obj, sizeof(Arc));
136 newObject = new Dimension();
137 memcpy(newObject, obj, sizeof(Dimension));
141 newObject = new Spline();
142 memcpy(newObject, obj, sizeof(Spline));
146 newObject = new Text();
147 memcpy(newObject, obj, sizeof(Text));
148 ((Text *)newObject)->s = ((Text *)obj)->s;
152 newObject = new Container();
153 ((Container *)newObject)->p[0] = obj->p[0];
154 ((Container *)newObject)->p[1] = obj->p[1];
155 ((Container *)newObject)->layer = obj->layer;
156 ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
161 if (newObject && (((Object *)newObject)->type != OTContainer))
162 ((Object *)newObject)->id = Global::objectID++;
164 return (Object *)newObject;
167 void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
169 VPVectorIter i = from.begin();
171 while (i != from.end())
173 Object * obj = (Object *)(*i);
185 VPVector MoveSelectedObjectsFrom(VPVector & from)
188 VPVectorIter i = from.begin();
190 while (i != from.end())
192 Object * obj = (Object *)(*i);
196 objects.push_back(*i);
206 //hmm, this won't work, as these are just pointers...
208 void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
210 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
212 Object * obj = (Object *)(*i);
215 dest.push_back(CopyObject2(obj));
219 VPVector CopySelectedObjects(VPVector & src)
223 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
225 Object * obj = (Object *)(*i);
228 copy.push_back(CopyObject2(obj));
234 void AddObjectsTo(VPVector & dest, VPVector & from)
236 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
240 void ClearSelected(VPVector & v)
242 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
243 ((Object *)(*i))->selected = false;
247 // Select all *visible* objects. If an object's layer is invisible, skip it.
249 void SelectAll(VPVector & v)
251 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
253 Object * obj = (Object *)(*i);
254 bool visible = !Global::layerHidden[obj->layer];
255 obj->selected = visible;
260 // Recursively go down thru the Container's vectors, deleting all the objects
261 // contained therein. Once that is done, the main Container can be deleted.
262 // We don't have to worry about the underlying std::vectors, as they have their
263 // own destructors--plus they don't take ownership of objects, which is why we
264 // have to keep track of that stuff ourselves. :-P Believe it or not, this is
265 // a Good Thing(TM). ;-)
267 void DeleteContents(VPVector & v)
269 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
271 Object * obj = (Object *)(*i);
273 if (obj->type == OTContainer)
274 DeleteContents(((Container *)obj)->objects);
282 void DeleteSelectedObjects(VPVector & v)
284 VPVectorIter i = v.begin();
288 Object * obj = (Object *)(*i);
301 // This is used to remove selected objects from one container in order to move
302 // them to a different container.
304 void RemoveSelectedObjects(VPVector & v)
306 VPVectorIter i = v.begin();
310 Object * obj = (Object *)(*i);
319 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
324 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
326 memcpy(&o, (Object *)(*i), sizeof(Object));
331 void RestorePointsTo(VPVector & v, std::vector<Object> & s)
333 std::vector<Object>::iterator i;
336 for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
338 Object * obj2 = (Object *)(*j);
339 obj2->p[0] = (*i).p[0];
340 obj2->p[1] = (*i).p[1];
341 obj2->angle[0] = (*i).angle[0];
342 obj2->angle[1] = (*i).angle[1];
343 //we don't do this because we want to keep selected & friends from changing
344 // memcpy(obj2, *j, sizeof(Object));
348 void RestorePointsTo(VPVector & v, VPVector & s)
350 for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
352 Object * objS = (Object *)(*i);
353 Object * objV = (Object *)(*j);
355 if (objV->type == OTContainer)
357 RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
361 objV->p[0] = objS->p[0];
362 objV->p[1] = objS->p[1];
363 objV->angle[0] = objS->angle[0];
364 objV->angle[1] = objS->angle[1];
365 //we don't do this because we want to keep selected & friends from changing
366 // memcpy(obj2, *j, sizeof(Object));
371 // Translate a single object; it it's a Container, translate all its contents,
372 // including subcontainers.
374 void TranslateObject(Object * obj, Point delta)
376 if (obj->type == OTContainer)
378 Container * c = (Container *)obj;
380 for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
381 TranslateObject((Object *)*i, delta);
389 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.
391 void TranslateContainer(Container * c, Point point, Point delta)
393 if (c->clicked == NULL)
395 // TranslateObject((Object *)c, delta);
400 //printf("TranslateContainer: boop (%i)\n", i++);
401 //we can set this to "point" and it won't move...
402 //do it *this* way, and non-enumerated clicks will do the right thing
403 Point clickedPoint = point - delta;
405 switch (c->clicked->type)
408 if (c->clicked->hitPoint[0])
409 clickedPoint = c->clicked->p[0];
410 else if (c->clicked->hitPoint[1])
411 clickedPoint = c->clicked->p[1];
412 else if (c->clicked->hitObject)
413 //Weirdness: some lines get a midpoint, some don't...
414 clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
419 if (c->clicked->hitPoint[0])
420 clickedPoint = c->clicked->p[0];
421 // else if (c->clicked->hitObject)
422 // clickedPoint = point - delta;
427 if (c->clicked->hitPoint[0])
428 clickedPoint = c->clicked->p[0];
429 else if (c->clicked->hitPoint[1])
430 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
431 else if (c->clicked->hitPoint[2])
432 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]);
433 // else if (c->clicked->hitObject)
434 // clickedPoint = point - delta;
445 Point clickedDelta = point - clickedPoint;
446 TranslateObject((Object *)c, clickedDelta);
450 // Translate all objects in the passed in vector, including Containers and all
451 // the objects they contain.
453 void TranslateObjects(VPVector & v, Point delta)
455 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
457 Object * obj = (Object *)(*i);
461 if (obj->type == OTContainer)
463 Container * c = (Container *)obj;
464 TranslateObjects(c->objects, delta);
470 // This does not *copy* the objects, it simply flattens out the pointers in the
471 // Container and all sub-Containers.
473 VPVector Flatten(Container * src)
477 for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
480 Object * obj = (Object *)(*i);
482 // Recursively add objects to the flat vector, if necessary
483 if (obj->type == OTContainer)
485 VPVector sub = Flatten((Container *)obj);
486 flat.insert(flat.end(), sub.begin(), sub.end());
494 // This does not *copy* the objects, it simply flattens out the pointers in the
495 // vector and all sub-Containers in the vector.
497 VPVector Flatten(VPVector src)
501 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
504 Object * obj = (Object *)(*i);
506 // Recursively add objects to the flat vector, if necessary
507 if (obj->type == OTContainer)
509 VPVector sub = Flatten(((Container *)obj)->objects);
510 flat.insert(flat.end(), sub.begin(), sub.end());