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()
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);
35 VPVector CopyObjects(VPVector & src)
39 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
41 Object * newObject = CopyObject2((Object *)(*i));
42 copy.push_back(newObject);
50 // Create a copy of the passed in object.
52 Object * CopyObject(Object * obj)
54 void * newObject = NULL;
59 newObject = new Line();
60 memcpy(newObject, obj, sizeof(Line));
63 newObject = new Circle();
64 memcpy(newObject, obj, sizeof(Circle));
67 newObject = new Ellipse();
68 memcpy(newObject, obj, sizeof(Ellipse));
71 newObject = new Arc();
72 memcpy(newObject, obj, sizeof(Arc));
75 newObject = new Dimension();
76 memcpy(newObject, obj, sizeof(Dimension));
79 newObject = new Spline();
80 memcpy(newObject, obj, sizeof(Spline));
83 newObject = new Text();
84 memcpy(newObject, obj, sizeof(Text));
85 ((Text *)newObject)->s = ((Text *)obj)->s;
88 newObject = new Container();
90 // memcpy(newObject, obj, sizeof(Line));
91 ((Container *)newObject)->p[0] = obj->p[0];
92 ((Container *)newObject)->p[1] = obj->p[1];
93 ((Container *)newObject)->layer = obj->layer;
94 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
101 if (newObject && (((Object *)newObject)->type != OTContainer))
102 ((Object *)newObject)->id = Global::objectID++;
104 return (Object *)newObject;
109 // Create a copy of the passed in object. This version calls the second
110 // version of CopyObjects() (with one parameter and a vector return value).
112 Object * CopyObject2(Object * obj)
114 void * newObject = NULL;
119 newObject = new Line();
120 memcpy(newObject, obj, sizeof(Line));
124 newObject = new Circle();
125 memcpy(newObject, obj, sizeof(Circle));
129 newObject = new Ellipse();
130 memcpy(newObject, obj, sizeof(Ellipse));
134 newObject = new Arc();
135 memcpy(newObject, obj, sizeof(Arc));
139 newObject = new Dimension();
140 memcpy(newObject, obj, sizeof(Dimension));
144 newObject = new Spline();
145 memcpy(newObject, obj, sizeof(Spline));
149 newObject = new Text();
150 memcpy(newObject, obj, sizeof(Text));
151 ((Text *)newObject)->s = ((Text *)obj)->s;
155 newObject = new Container();
156 ((Container *)newObject)->p[0] = obj->p[0];
157 ((Container *)newObject)->p[1] = obj->p[1];
158 ((Container *)newObject)->layer = obj->layer;
159 ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
164 if (newObject && (((Object *)newObject)->type != OTContainer))
165 ((Object *)newObject)->id = Global::objectID++;
167 return (Object *)newObject;
171 void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
173 VPVectorIter i = from.begin();
175 while (i != from.end())
177 Object * obj = (Object *)(*i);
190 VPVector MoveSelectedObjectsFrom(VPVector & from)
193 VPVectorIter i = from.begin();
195 while (i != from.end())
197 Object * obj = (Object *)(*i);
201 objects.push_back(*i);
212 //hmm, this won't work, as these are just pointers...
214 void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
216 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
218 Object * obj = (Object *)(*i);
221 dest.push_back(CopyObject2(obj));
226 VPVector CopySelectedObjects(VPVector & src)
230 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
232 Object * obj = (Object *)(*i);
235 copy.push_back(CopyObject2(obj));
242 void AddObjectsTo(VPVector & dest, VPVector & from)
244 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
249 void ClearSelected(VPVector & v)
251 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
252 ((Object *)(*i))->selected = false;
257 // Select all *visible* objects. If an object's layer is invisible, skip it.
259 void SelectAll(VPVector & v)
261 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
263 Object * obj = (Object *)(*i);
264 bool visible = !Global::layerHidden[obj->layer];
265 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);
294 void DeleteSelectedObjects(VPVector & v)
296 VPVectorIter i = v.begin();
300 Object * obj = (Object *)(*i);
314 // This is used to remove selected objects from one container in order to move
315 // them to a different container.
317 void RemoveSelectedObjects(VPVector & v)
319 VPVectorIter i = v.begin();
323 Object * obj = (Object *)(*i);
333 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
338 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
340 memcpy(&o, (Object *)(*i), sizeof(Object));
346 void RestorePointsTo(VPVector & v, std::vector<Object> & s)
348 std::vector<Object>::iterator i;
351 for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
353 Object * obj2 = (Object *)(*j);
354 obj2->p[0] = (*i).p[0];
355 obj2->p[1] = (*i).p[1];
356 obj2->angle[0] = (*i).angle[0];
357 obj2->angle[1] = (*i).angle[1];
358 //we don't do this because we want to keep selected & friends from changing
359 // memcpy(obj2, *j, sizeof(Object));
364 void RestorePointsTo(VPVector & v, VPVector & s)
366 for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
368 Object * objS = (Object *)(*i);
369 Object * objV = (Object *)(*j);
371 if (objV->type == OTContainer)
373 RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
377 objV->p[0] = objS->p[0];
378 objV->p[1] = objS->p[1];
379 objV->angle[0] = objS->angle[0];
380 objV->angle[1] = objS->angle[1];
381 //we don't do this because we want to keep selected & friends from changing
382 // memcpy(obj2, *j, sizeof(Object));
388 // Translate a single object; it it's a Container, translate all its contents,
389 // including subcontainers.
391 void TranslateObject(Object * obj, Point delta)
393 if (obj->type == OTContainer)
395 Container * c = (Container *)obj;
397 for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
398 TranslateObject((Object *)*i, delta);
407 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.
409 void TranslateContainer(Container * c, Point point, Point delta)
411 if (c->clicked == NULL)
413 // TranslateObject((Object *)c, delta);
418 //printf("TranslateContainer: boop (%i)\n", i++);
419 //we can set this to "point" and it won't move...
420 //do it *this* way, and non-enumerated clicks will do the right thing
421 Point clickedPoint = point - delta;
423 switch (c->clicked->type)
426 if (c->clicked->hitPoint[0])
427 clickedPoint = c->clicked->p[0];
428 else if (c->clicked->hitPoint[1])
429 clickedPoint = c->clicked->p[1];
430 else if (c->clicked->hitObject)
431 //Weirdness: some lines get a midpoint, some don't...
432 clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
437 if (c->clicked->hitPoint[0])
438 clickedPoint = c->clicked->p[0];
439 // else if (c->clicked->hitObject)
440 // clickedPoint = point - delta;
445 if (c->clicked->hitPoint[0])
446 clickedPoint = c->clicked->p[0];
447 else if (c->clicked->hitPoint[1])
448 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
449 else if (c->clicked->hitPoint[2])
450 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]);
451 // else if (c->clicked->hitObject)
452 // clickedPoint = point - delta;
463 Point clickedDelta = point - clickedPoint;
464 TranslateObject((Object *)c, clickedDelta);
469 // Translate all objects in the passed in vector, including Containers and all
470 // the objects they contain.
472 void TranslateObjects(VPVector & v, Point delta)
474 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
476 Object * obj = (Object *)(*i);
480 if (obj->type == OTContainer)
482 Container * c = (Container *)obj;
483 TranslateObjects(c->objects, delta);
490 // This does not *copy* the objects, it simply flattens out the pointers in the
491 // Container and all sub-Containers.
493 VPVector Flatten(Container * src)
497 for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
500 Object * obj = (Object *)(*i);
502 // Recursively add objects to the flat vector, if necessary
503 if (obj->type == OTContainer)
505 VPVector sub = Flatten((Container *)obj);
506 flat.insert(flat.end(), sub.begin(), sub.end());
515 // This does not *copy* the objects, it simply flattens out the pointers in the
516 // vector and all sub-Containers in the vector.
518 VPVector Flatten(VPVector src)
522 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
525 Object * obj = (Object *)(*i);
527 // Recursively add objects to the flat vector, if necessary
528 if (obj->type == OTContainer)
530 VPVector sub = Flatten(((Container *)obj)->objects);
531 flat.insert(flat.end(), sub.begin(), sub.end());