1 // rs_entitycontainer.cpp
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/28/2010 Added this text. :-)
17 #include "rs_entitycontainer.h"
20 #include "rs_dimension.h"
24 #include "rs_polyline.h"
26 #include "rs_insert.h"
27 #include "rs_spline.h"
28 #include "rs_information.h"
29 #include "graphicview.h"
30 #include "paintinterface.h"
32 bool RS_EntityContainer::autoUpdateBorders = true;
35 * Default constructor.
37 * @param owner True if we own and also delete the entities.
39 RS_EntityContainer::RS_EntityContainer(RS_EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
40 RS_Entity(parent), entityIterator(entities)
41 //NOTE: This constructor may not be explicitly OR implicitly called, meaning that
42 // entityIterator will not get initialized!
44 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
45 // entities.setAutoDelete(owner);
46 RS_DEBUG->print("RS_EntityContainer::RS_EntityContainer: owner: %d", (int)owner);
48 //autoUpdateBorders = true;
52 * Copy constructor. Makes a deep copy of all entities.
55 RS_EntityContainer::RS_EntityContainer(const RS_EntityContainer& ec)
64 RS_EntityContainer::~RS_EntityContainer()
69 RS_Entity * RS_EntityContainer::clone()
71 // RS_DEBUG->print("RS_EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
72 RS_EntityContainer * ec = new RS_EntityContainer(*this);
73 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
74 // ec->entities.setAutoDelete(entities.autoDelete());
75 // RS_DEBUG->print("RS_EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete());
83 * Detaches shallow copies and creates deep copies of all subentities.
84 * This is called after cloning entity containers.
86 void RS_EntityContainer::detach()
88 // Q3PtrList<RS_Entity> tmp;
89 QList<RS_Entity *> tmp;
90 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
91 // bool autoDel = entities.autoDelete();
92 // RS_DEBUG->print("RS_EntityContainer::detach: autoDel: %d", (int)autoDel);
93 // entities.setAutoDelete(false);
95 // make deep copies of all entities:
96 for(RS_Entity * e=firstEntity(); e!=NULL; e=nextEntity())
98 if (!e->getFlag(RS2::FlagTemp))
100 tmp.append(e->clone());
104 // clear shared pointers:
106 // entities.setAutoDelete(autoDel);
108 // point to new deep copies:
109 // for(RS_Entity * e=tmp.first(); e!=NULL; e=tmp.next())
110 for(int i=0; i<tmp.size(); i++)
112 RS_Entity * e = tmp[i];
118 /** @return RS2::EntityContainer */
119 /*virtual*/ RS2::EntityType RS_EntityContainer::rtti() const
121 return RS2::EntityContainer;
124 void RS_EntityContainer::reparent(RS_EntityContainer * parent)
126 RS_Entity::reparent(parent);
129 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
136 * @return true: because entities made from this class
137 * and subclasses are containers for other entities.
139 /*virtual*/ bool RS_EntityContainer::isContainer() const
145 * @return false: because entities made from this class
146 * and subclasses are containers for other entities.
148 /*virtual*/ bool RS_EntityContainer::isAtomic() const
154 * Called when the undo state changed. Forwards the event to all sub-entities.
156 * @param undone true: entity has become invisible.
157 * false: entity has become visible.
159 void RS_EntityContainer::undoStateChanged(bool undone)
161 RS_Entity::undoStateChanged(undone);
163 // ! don't pass on to subentities. undo list handles them
165 /*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
167 e=nextEntity(RS2::ResolveNone)) {
168 e->setUndoState(undone);
172 void RS_EntityContainer::setVisible(bool v)
174 RS_DEBUG->print("RS_EntityContainer::setVisible: %d", v);
175 RS_Entity::setVisible(v);
178 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
180 RS_DEBUG->print("RS_EntityContainer::setVisible: subentity: %d", v);
186 * @return Total length of all entities in this container.
188 double RS_EntityContainer::getLength()
192 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
196 double l = e->getLength();
214 * Selects this entity.
216 bool RS_EntityContainer::setSelected(bool select)
218 // This entity's select:
219 if (RS_Entity::setSelected(select))
221 // All sub-entity's select:
222 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
226 e->setSelected(select);
239 * Toggles select on this entity.
241 bool RS_EntityContainer::toggleSelected()
243 // Toggle this entity's select:
244 if (RS_Entity::toggleSelected())
247 // Toggle all sub-entity's select:
248 /*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
250 e=nextEntity(RS2::ResolveNone)) {
262 * Selects all entities within the given area.
264 * @param select True to select, False to deselect the entities.
266 void RS_EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
270 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
276 if (e->isInWindow(v1, v2))
278 //e->setSelected(select);
281 else if (cross == true)
285 RS_Line(NULL, RS_LineData(v1, Vector(v2.x, v1.y))),
286 RS_Line(NULL, RS_LineData(Vector(v2.x, v1.y), v2)),
287 RS_Line(NULL, RS_LineData(v2, Vector(v1.x, v2.y))),
288 RS_Line(NULL, RS_LineData(Vector(v1.x, v2.y), v1))
292 if (e->isContainer())
294 RS_EntityContainer * ec = (RS_EntityContainer *)e;
296 for(RS_Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false;
297 se=ec->nextEntity(RS2::ResolveAll))
299 for(int i=0; i<4; ++i)
301 sol = RS_Information::getIntersection(se, &l[i], true);
313 for(int i=0; i<4; ++i)
315 sol = RS_Information::getIntersection(e, &l[i], true);
329 e->setSelected(select);
335 * Adds a entity to this container and updates the borders of this
336 * entity-container if autoUpdateBorders is true.
338 void RS_EntityContainer::addEntity(RS_Entity * entity)
342 RS_LayerList* lst = getDocument()->getLayerList();
344 RS_Layer* l = lst->getActive();
345 if (l!=NULL && l->isLocked()) {
351 //printf("RS_EntityContainer::addEntity(): entity=%08X\n", entity);
356 if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch)
357 entities.prepend(entity);
359 entities.append(entity);
361 if (autoUpdateBorders)
362 adjustBorders(entity);
363 //printf(" # of entities=%d\n", entities.size());
367 * Inserts a entity to this container at the given position and updates
368 * the borders of this entity-container if autoUpdateBorders is true.
370 void RS_EntityContainer::insertEntity(int index, RS_Entity * entity)
375 entities.insert(index, entity);
377 if (autoUpdateBorders)
378 adjustBorders(entity);
382 * Replaces the entity at the given index with the given entity
383 * and updates the borders of this entity-container if autoUpdateBorders is true.
385 void RS_EntityContainer::replaceEntity(int index, RS_Entity * entity)
390 entities.replace(index, entity);
392 if (autoUpdateBorders)
393 adjustBorders(entity);
397 * Removes an entity from this container and updates the borders of
398 * this entity-container if autoUpdateBorders is true.
400 bool RS_EntityContainer::removeEntity(RS_Entity * entity)
402 // bool ret = entities.remove(entity);
403 bool ret = (bool)entities.removeAll(entity);
405 if (autoUpdateBorders)
412 * Erases all entities in this container and resets the borders..
414 void RS_EntityContainer::clear()
421 * Counts all entities (branches of the tree).
423 unsigned long int RS_EntityContainer::count()
425 return entities.count();
429 * Counts all entities (leaves of the tree).
431 unsigned long int RS_EntityContainer::countDeep()
433 unsigned long int c = 0;
435 for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
444 * Counts the selected entities in this container.
446 unsigned long int RS_EntityContainer::countSelected()
448 unsigned long int c = 0;
450 for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
462 * Enables / disables automatic update of borders on entity removals
463 * and additions. By default this is turned on.
465 /*virtual*/ void RS_EntityContainer::setAutoUpdateBorders(bool enable)
467 autoUpdateBorders = enable;
471 * Adjusts the borders of this graphic (max/min values)
473 void RS_EntityContainer::adjustBorders(RS_Entity * entity)
475 //RS_DEBUG->print("RS_EntityContainer::adjustBorders");
480 // make sure a container is not empty (otherwise the border
481 // would get extended to 0/0):
482 if (!entity->isContainer() || entity->count() > 0)
484 minV = Vector::minimum(entity->getMin(), minV);
485 maxV = Vector::maximum(entity->getMax(), maxV);
488 // Notify parents. The border for the parent might
489 // also change TODO: Check for efficiency
491 //parent->adjustBorders(this);
497 * Recalculates the borders of this entity container.
499 void RS_EntityContainer::calculateBorders()
501 RS_DEBUG->print("RS_EntityContainer::calculateBorders");
505 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
507 RS_Layer * layer = e->getLayer();
509 RS_DEBUG->print("RS_EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
511 if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
513 e->calculateBorders();
518 RS_DEBUG->print("RS_EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y);
520 // needed for correcting corrupt data (PLANS.dxf)
521 if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
522 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
528 if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
529 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
535 RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
537 //RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
539 //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
540 //RS_Entity::calculateBorders();
544 * Recalculates the borders of this entity container including
545 * invisible entities.
547 void RS_EntityContainer::forcedCalculateBorders()
549 //RS_DEBUG->print("RS_EntityContainer::calculateBorders");
553 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
555 //RS_Layer* layer = e->getLayer();
557 if (e->isContainer())
559 ((RS_EntityContainer *)e)->forcedCalculateBorders();
563 e->calculateBorders();
569 // needed for correcting corrupt data (PLANS.dxf)
570 if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
571 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
577 if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
578 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
584 //RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
586 //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
587 //RS_Entity::calculateBorders();
591 * Updates all Dimension entities in this container and
592 * reposition their labels.
594 void RS_EntityContainer::updateDimensions()
596 RS_DEBUG->print("RS_EntityContainer::updateDimensions()");
598 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
600 // e=nextEntity(RS2::ResolveNone)) {
603 // Q3PtrListIterator<RS_Entity> it = createIterator();
604 QListIterator<RS_Entity *> it = createIterator();
605 // return QListIterator<RS_Entity *>(entities);
609 while ((e = it.current()) != NULL)
613 if (RS_Information::isDimension(e->rtti()))
615 // update and reposition label:
616 ((RS_Dimension *)e)->update(true);
618 else if (e->isContainer())
620 ((RS_EntityContainer *)e)->updateDimensions();
624 for(int i=0; i<entities.size(); i++)
626 RS_Entity * e = entities[i];
628 if (RS_Information::isDimension(e->rtti()))
629 // update and reposition label:
630 ((RS_Dimension *)e)->update(true);
631 else if (e->isContainer())
632 ((RS_EntityContainer *)e)->updateDimensions();
636 RS_DEBUG->print("RS_EntityContainer::updateDimensions() OK");
640 * Updates all Insert entities in this container.
642 void RS_EntityContainer::updateInserts()
644 RS_DEBUG->print("RS_EntityContainer::updateInserts()");
646 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
648 // e=nextEntity(RS2::ResolveNone)) {
650 Q3PtrListIterator<RS_Entity> it = createIterator();
653 while ((e = it.current()) != NULL)
656 //// Only update our own inserts and not inserts of inserts
657 if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
659 ((RS_Insert *)e)->update();
661 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
663 ((RS_EntityContainer *)e)->updateInserts();
667 for(int i=0; i<entities.size(); i++)
669 RS_Entity * e = entities[i];
671 //// Only update our own inserts and not inserts of inserts
672 if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
673 ((RS_Insert *)e)->update();
674 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
675 ((RS_EntityContainer *)e)->updateInserts();
679 RS_DEBUG->print("RS_EntityContainer::updateInserts() OK");
683 * Renames all inserts with name 'oldName' to 'newName'. This is
684 * called after a block was rename to update the inserts.
686 void RS_EntityContainer::renameInserts(const QString& oldName, const QString& newName)
688 RS_DEBUG->print("RS_EntityContainer::renameInserts()");
690 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
692 // e=nextEntity(RS2::ResolveNone)) {
695 Q3PtrListIterator<RS_Entity> it = createIterator();
697 while ( (e = it.current()) != NULL ) {
700 if (e->rtti()==RS2::EntityInsert) {
701 RS_Insert* i = ((RS_Insert*)e);
702 if (i->getName()==oldName) {
705 } else if (e->isContainer()) {
706 ((RS_EntityContainer*)e)->renameInserts(oldName, newName);
710 for(int i=0; i<entities.size(); i++)
712 RS_Entity * e = entities[i];
714 if (e->rtti() == RS2::EntityInsert)
716 RS_Insert * i = ((RS_Insert *)e);
718 if (i->getName() == oldName)
721 else if (e->isContainer())
722 ((RS_EntityContainer *)e)->renameInserts(oldName, newName);
726 RS_DEBUG->print("RS_EntityContainer::renameInserts() OK");
731 * Updates all Spline entities in this container.
733 void RS_EntityContainer::updateSplines()
735 RS_DEBUG->print("RS_EntityContainer::updateSplines()");
737 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
739 // e=nextEntity(RS2::ResolveNone)) {
741 Q3PtrListIterator<RS_Entity> it = createIterator();
743 while ( (e = it.current()) != NULL ) {
745 //// Only update our own inserts and not inserts of inserts
746 if (e->rtti()==RS2::EntitySpline /*&& e->getParent()==this*/) {
747 ((RS_Spline*)e)->update();
748 } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
749 ((RS_EntityContainer*)e)->updateSplines();
753 for(int i=0; i<entities.size(); i++)
755 RS_Entity * e = entities[i];
757 //// Only update our own inserts and not inserts of inserts
758 if (e->rtti() == RS2::EntitySpline /*&& e->getParent()==this*/)
759 ((RS_Spline *)e)->update();
760 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
761 ((RS_EntityContainer *)e)->updateSplines();
765 RS_DEBUG->print("RS_EntityContainer::updateSplines() OK");
769 * Updates the sub entities of this container.
771 void RS_EntityContainer::update()
773 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
775 // e=nextEntity(RS2::ResolveNone)) {
777 Q3PtrListIterator<RS_Entity> it = createIterator();
779 while ( (e = it.current()) != NULL ) {
784 for(int i=0; i<entities.size(); i++)
786 // RS_Entity * e = entities[i];
788 entities[i]->update();
794 * Returns the first entity or NULL if this graphic is empty.
797 RS_Entity * RS_EntityContainer::firstEntity(RS2::ResolveLevel level)
801 case RS2::ResolveNone:
802 // return entities.first();
803 // entityIterator.toFront();
804 entityIterator = entities;
805 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
808 case RS2::ResolveAllButInserts:
811 // RS_Entity * e = entities.first();
812 // entityIterator.toFront();
813 entityIterator = entities;
814 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
816 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
818 subContainer = (RS_EntityContainer *)e;
819 e = ((RS_EntityContainer *)e)->firstEntity(level);
825 e = nextEntity(level);
833 case RS2::ResolveAll:
836 // RS_Entity * e = entities.first();
837 // entityIterator.toFront();
838 entityIterator = entities;
839 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
841 if (e != NULL && e->isContainer())
843 subContainer = (RS_EntityContainer *)e;
844 e = ((RS_EntityContainer *)e)->firstEntity(level);
850 e = nextEntity(level);
863 * Returns the last entity or \p NULL if this graphic is empty.
865 * @param level \li \p 0 Groups are not resolved
866 * \li \p 1 (default) only Groups are resolved
867 * \li \p 2 all Entity Containers are resolved
869 RS_Entity * RS_EntityContainer::lastEntity(RS2::ResolveLevel level)
873 case RS2::ResolveNone:
874 // return entities.last();
875 entityIterator = entities;
876 entityIterator.toBack();
877 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
880 case RS2::ResolveAllButInserts:
882 // RS_Entity * e = entities.last();
883 entityIterator = entities;
884 entityIterator.toBack();
885 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
888 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
890 subContainer = (RS_EntityContainer *)e;
891 e = ((RS_EntityContainer *)e)->lastEntity(level);
898 case RS2::ResolveAll:
900 // RS_Entity * e = entities.last();
901 entityIterator = entities;
902 entityIterator.toBack();
903 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
906 if (e != NULL && e->isContainer())
908 subContainer = (RS_EntityContainer *)e;
909 e = ((RS_EntityContainer *)e)->lastEntity(level);
921 * Returns the next entity or container or \p NULL if the last entity
922 * returned by \p next() was the last entity in the container.
924 RS_Entity * RS_EntityContainer::nextEntity(RS2::ResolveLevel level)
928 case RS2::ResolveNone:
929 // return entities.next();
930 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
933 case RS2::ResolveAllButInserts:
935 RS_Entity * e = NULL;
937 if (subContainer != NULL)
939 e = subContainer->nextEntity(level);
947 // e = entities.next();
948 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
953 // e = entities.next();
954 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
957 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
959 subContainer = (RS_EntityContainer *)e;
960 e = ((RS_EntityContainer *)e)->firstEntity(level);
966 e = nextEntity(level);
974 case RS2::ResolveAll:
976 RS_Entity * e = NULL;
978 if (subContainer != NULL)
980 e = subContainer->nextEntity(level);
985 // e = entities.next();
986 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
990 // e = entities.next();
991 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
994 if (e != NULL && e->isContainer())
996 subContainer = (RS_EntityContainer *)e;
997 e = ((RS_EntityContainer *)e)->firstEntity(level);
1002 subContainer = NULL;
1003 e = nextEntity(level);
1015 * Returns the prev entity or container or \p NULL if the last entity
1016 * returned by \p prev() was the first entity in the container.
1018 RS_Entity * RS_EntityContainer::prevEntity(RS2::ResolveLevel level)
1020 RS_Entity * e = NULL;
1024 case RS2::ResolveNone:
1025 // return entities.prev();
1026 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1029 case RS2::ResolveAllButInserts:
1032 if (subContainer != NULL)
1034 e = subContainer->prevEntity(level);
1039 // e = entities.prev();
1040 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1044 // e = entities.prev();
1045 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1048 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
1050 subContainer = (RS_EntityContainer *)e;
1051 e = ((RS_EntityContainer *)e)->lastEntity(level);
1056 subContainer = NULL;
1057 e = prevEntity(level);
1063 case RS2::ResolveAll:
1066 if (subContainer != NULL)
1068 e = subContainer->prevEntity(level);
1073 // e = entities.prev();
1074 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1078 // e = entities.prev();
1079 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1082 if (e != NULL && e->isContainer())
1084 subContainer = (RS_EntityContainer *)e;
1085 e = ((RS_EntityContainer *)e)->lastEntity(level);
1090 subContainer = NULL;
1091 e = prevEntity(level);
1102 * @return Entity at the given index or NULL if the index is out of range.
1104 RS_Entity * RS_EntityContainer::entityAt(uint index)
1106 return entities.at(index);
1110 * @return Current index.
1112 int RS_EntityContainer::entityAt()
1114 #warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)"
1115 // return entities.at();
1120 * Finds the given entity and makes it the current entity if found.
1122 int RS_EntityContainer::findEntity(RS_Entity * entity)
1124 // return entities.find(entity);
1126 entityIterator.toFront();
1127 entityIterator.findNext(entity);
1129 return entities.indexOf(entity);
1133 * @return The current entity.
1135 RS_Entity * RS_EntityContainer::currentEntity()
1137 // return entities.current();
1139 // We really need to refactor this crap, this is the way it is now to support
1140 // the old broken way of doing things
1141 return entityIterator.peekNext();
1145 #warning "!!! Not needed anymore !!!"
1147 * Returns the copy to a new iterator for traversing the entities.
1149 //Q3PtrListIterator<RS_Entity> RS_EntityContainer::createIterator()
1150 QListIterator<RS_Entity *> RS_EntityContainer::createIterator()
1152 // return Q3PtrListIterator<RS_Entity>(entities);
1153 return QListIterator<RS_Entity *>(entities);
1157 /*virtual*/ bool RS_EntityContainer::isEmpty()
1159 return (count() == 0);
1163 * @return The point which is closest to 'coord'
1164 * (one of the vertexes)
1166 Vector RS_EntityContainer::getNearestEndpoint(const Vector & coord, double * dist)
1168 double minDist = RS_MAXDOUBLE; // minimum measured distance
1169 double curDist; // currently measured distance
1170 Vector closestPoint(false); // closest found endpoint
1171 Vector point; // endpoint found
1173 //Q3PtrListIterator<RS_Entity> it = createIterator();
1175 //while ( (en = it.current()) != NULL ) {
1177 for (RS_Entity* en = firstEntity();
1179 en = nextEntity()) {
1181 if (en->isVisible()) {
1182 point = en->getNearestEndpoint(coord, &curDist);
1183 if (point.valid && curDist<minDist) {
1184 closestPoint = point;
1193 return closestPoint;
1196 Vector RS_EntityContainer::getNearestPointOnEntity(const Vector & coord,
1197 bool onEntity, double * dist, RS_Entity ** entity)
1199 Vector point(false);
1201 RS_Entity * e = getNearestEntity(coord, dist, RS2::ResolveNone);
1203 if (e && e->isVisible())
1204 point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1209 Vector RS_EntityContainer::getNearestCenter(const Vector & coord, double * dist)
1211 Vector point(false);
1212 RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1215 point = closestEntity->getNearestCenter(coord, dist);
1220 Vector RS_EntityContainer::getNearestMiddle(const Vector & coord, double * dist)
1222 Vector point(false);
1223 RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1226 point = closestEntity->getNearestMiddle(coord, dist);
1231 Vector RS_EntityContainer::getNearestDist(double distance, const Vector & coord,
1234 Vector point(false);
1235 RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1238 point = closestEntity->getNearestDist(distance, coord, dist);
1244 * @return The intersection which is closest to 'coord'
1246 Vector RS_EntityContainer::getNearestIntersection(const Vector & coord,
1249 double minDist = RS_MAXDOUBLE; // minimum measured distance
1250 double curDist; // currently measured distance
1251 Vector closestPoint(false); // closest found endpoint
1252 Vector point; // endpoint found
1253 VectorSolutions sol;
1254 RS_Entity * closestEntity;
1256 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1260 for(RS_Entity * en=firstEntity(RS2::ResolveAll); en!=NULL;
1261 en = nextEntity(RS2::ResolveAll))
1263 if (en->isVisible() && en!=closestEntity)
1265 sol = RS_Information::getIntersection(closestEntity, en, true);
1267 for(int i=0; i<4; i++)
1273 curDist = coord.distanceTo(point);
1275 if (curDist < minDist)
1277 closestPoint = point;
1289 return closestPoint;
1292 Vector RS_EntityContainer::getNearestRef(const Vector & coord, double * dist)
1294 double minDist = RS_MAXDOUBLE; // minimum measured distance
1295 double curDist; // currently measured distance
1296 Vector closestPoint(false); // closest found endpoint
1297 Vector point; // endpoint found
1299 for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1301 if (en->isVisible())
1303 point = en->getNearestRef(coord, &curDist);
1305 if (point.valid && curDist < minDist)
1307 closestPoint = point;
1316 return closestPoint;
1319 Vector RS_EntityContainer::getNearestSelectedRef(const Vector & coord,
1322 double minDist = RS_MAXDOUBLE; // minimum measured distance
1323 double curDist; // currently measured distance
1324 Vector closestPoint(false); // closest found endpoint
1325 Vector point; // endpoint found
1327 for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1329 if (en->isVisible() && en->isSelected() && !en->isParentSelected())
1331 point = en->getNearestSelectedRef(coord, &curDist);
1333 if (point.valid && curDist < minDist)
1335 closestPoint = point;
1344 return closestPoint;
1347 double RS_EntityContainer::getDistanceToPoint(const Vector & coord,
1348 RS_Entity ** entity, RS2::ResolveLevel level, double solidDist)
1350 RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint");
1352 double minDist = RS_MAXDOUBLE; // minimum measured distance
1353 double curDist; // currently measured distance
1354 RS_Entity * closestEntity = NULL; // closest entity found
1355 RS_Entity * subEntity = NULL;
1358 for(RS_Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level))
1362 RS_DEBUG->print("entity: getDistanceToPoint");
1363 RS_DEBUG->print("entity: %d", e->rtti());
1364 curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1365 RS_DEBUG->print("entity: getDistanceToPoint: OK");
1367 if (curDist<minDist)
1369 if (level != RS2::ResolveAll)
1372 closestEntity = subEntity;
1380 *entity = closestEntity;
1382 RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK");
1386 RS_Entity * RS_EntityContainer::getNearestEntity(const Vector & coord,
1387 double * dist, RS2::ResolveLevel level)
1389 RS_DEBUG->print("RS_EntityContainer::getNearestEntity");
1390 RS_Entity * e = NULL;
1392 // distance for points inside solids:
1393 double solidDist = RS_MAXDOUBLE;
1398 double d = getDistanceToPoint(coord, &e, level, solidDist);
1400 if (e && e->isVisible() == false)
1403 // if d is negative, use the default distance (used for points inside solids)
1407 RS_DEBUG->print("RS_EntityContainer::getNearestEntity: OK");
1412 * Rearranges the atomic entities in this container in a way that connected
1413 * entities are stored in the right order and direction.
1414 * Non-recoursive. Only affects atomic entities in this container.
1416 * @retval true all contours were closed
1417 * @retval false at least one contour is not closed
1419 bool RS_EntityContainer::optimizeContours()
1421 RS_DEBUG->print("RS_EntityContainer::optimizeContours");
1423 Vector current(false);
1424 Vector start(false);
1425 RS_EntityContainer tmp;
1427 bool changed = false;
1430 for(uint ci=0; ci<count(); ++ci)
1432 RS_Entity * e1=entityAt(ci);
1434 if (e1 && e1->isEdge() && !e1->isContainer() && !e1->isProcessed())
1436 RS_AtomicEntity * ce = (RS_AtomicEntity *)e1;
1438 // next contour start:
1439 ce->setProcessed(true);
1440 tmp.addEntity(ce->clone());
1441 current = ce->getEndpoint();
1442 start = ce->getStartpoint();
1444 // find all connected entities:
1450 for(uint ei=0; ei<count(); ++ei)
1452 RS_Entity * e2=entityAt(ei);
1454 if (e2 != NULL && e2->isEdge() && !e2->isContainer() &&
1457 RS_AtomicEntity * e = (RS_AtomicEntity *)e2;
1459 if (e->getStartpoint().distanceTo(current) < 1.0e-4)
1461 e->setProcessed(true);
1462 tmp.addEntity(e->clone());
1463 current = e->getEndpoint();
1466 else if (e->getEndpoint().distanceTo(current) < 1.0e-4)
1468 e->setProcessed(true);
1469 RS_AtomicEntity * cl = (RS_AtomicEntity *)e->clone();
1472 current = cl->getEndpoint();
1484 if (current.distanceTo(start) > 1.0e-4)
1489 // remove all atomic entities:
1496 for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1498 if (!en->isContainer())
1508 // add new sorted entities:
1509 for(RS_Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity())
1511 en->setProcessed(false);
1512 addEntity(en->clone());
1515 RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
1519 bool RS_EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2)
1521 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1523 if (e->hasEndpointsWithinWindow(v1, v2))
1530 void RS_EntityContainer::move(Vector offset)
1532 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1535 if (autoUpdateBorders)
1539 void RS_EntityContainer::rotate(Vector center, double angle)
1541 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1542 e->rotate(center, angle);
1544 if (autoUpdateBorders)
1548 void RS_EntityContainer::scale(Vector center, Vector factor)
1550 if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE)
1552 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1553 e->scale(center, factor);
1556 if (autoUpdateBorders)
1560 void RS_EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2)
1562 if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6)
1564 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1565 e->mirror(axisPoint1, axisPoint2);
1569 void RS_EntityContainer::stretch(Vector firstCorner, Vector secondCorner,
1572 if (getMin().isInWindow(firstCorner, secondCorner) &&
1573 getMax().isInWindow(firstCorner, secondCorner))
1579 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1580 e->stretch(firstCorner, secondCorner, offset);
1583 // some entitiycontainers might need an update (e.g. RS_Leader):
1587 void RS_EntityContainer::moveRef(const Vector & ref, const Vector & offset)
1589 for(RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1590 e->moveRef(ref, offset);
1592 if (autoUpdateBorders)
1596 void RS_EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1598 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1599 e->moveSelectedRef(ref, offset);
1601 if (autoUpdateBorders)
1605 void RS_EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
1607 if (!painter || !view)
1610 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1613 if (e->rtti() == RS2::EntityText)
1615 std::cout << "About to draw TEXT entity... "
1616 << "TEXT=\"" << ((RS_Text *)e)->getText().toAscii().data() << "\"" << std::endl;
1618 //OK, we have text, but no insert entities at least none that are drawn...
1619 //Ah! But with a standard text entity, it DOES have them!
1620 else if (e->rtti() == RS2::EntityInsert)
1622 std::cout << "About to draw INSERT entity... "
1623 << "INSERT=\"" << ((RS_Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl;
1626 view->drawEntity(e);
1633 * Dumps the entities to stdout.
1635 std::ostream & operator<<(std::ostream & os, RS_EntityContainer & ec)
1637 static int indent = 0;
1638 char * tab = new char[indent * 2 + 1];
1640 for(int i=0; i<indent*2; i++)
1643 tab[indent * 2] = '\0';
1645 unsigned long int id = ec.getId();
1647 os << tab << "EntityContainer[" << id << "]: \n";
1648 os << tab << "Borders[" << id << "]: "
1649 << ec.minV << " - " << ec.maxV << "\n";
1650 //os << tab << "Unit[" << id << "]: "
1651 //<< RS_Units::unit2string (ec.unit) << "\n";
1654 os << tab << "Layer[" << id << "]: "
1655 << ec.getLayer()->getName().toLatin1().data() << "\n";
1659 os << tab << "Layer[" << id << "]: <NULL>\n";
1661 //os << ec.layerList << "\n";
1663 os << tab << " Flags[" << id << "]: "
1664 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1665 os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1666 os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1669 os << tab << "Entities[" << id << "]: \n";
1672 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1673 for(int i=0; i<ec.entities.size(); i++)
1675 RS_Entity * t = ec.entities[i];
1676 s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1677 os << s.toAscii().data();
1679 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1680 os << s.toAscii().data();
1682 for(RS_Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1686 case RS2::EntityInsert:
1687 os << tab << *((RS_Insert *)t);
1688 os << tab << *((RS_Entity *)t);
1689 os << tab << *((RS_EntityContainer *)t);
1692 if (t->isContainer())
1693 os << tab << *((RS_EntityContainer *)t);
1701 os << tab << "\n\n";