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 "entitycontainer.h"
20 #include "dimension.h"
21 #include "mathextra.h"
28 #include "information.h"
29 #include "graphicview.h"
30 #include "paintinterface.h"
32 bool EntityContainer::autoUpdateBorders = true;
35 * Default constructor.
37 * @param owner True if we own and also delete the entities.
39 EntityContainer::EntityContainer(EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
40 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 DEBUG->print("EntityContainer::EntityContainer: owner: %d", (int)owner);
48 //autoUpdateBorders = true;
52 * Copy constructor. Makes a deep copy of all entities.
55 EntityContainer::EntityContainer(const EntityContainer& ec)
64 EntityContainer::~EntityContainer()
69 Entity * EntityContainer::clone()
71 // DEBUG->print("EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
72 EntityContainer * ec = new EntityContainer(*this);
73 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
74 // ec->entities.setAutoDelete(entities.autoDelete());
75 // DEBUG->print("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 EntityContainer::detach()
88 // Q3PtrList<Entity> tmp;
90 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
91 // bool autoDel = entities.autoDelete();
92 // DEBUG->print("EntityContainer::detach: autoDel: %d", (int)autoDel);
93 // entities.setAutoDelete(false);
95 // make deep copies of all entities:
96 for(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(Entity * e=tmp.first(); e!=NULL; e=tmp.next())
110 for(int i=0; i<tmp.size(); i++)
118 /** @return RS2::EntityContainer */
119 /*virtual*/ RS2::EntityType EntityContainer::rtti() const
121 return RS2::EntityContainer;
124 void EntityContainer::reparent(EntityContainer * parent)
126 Entity::reparent(parent);
129 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
134 * @return true: because entities made from this class
135 * and subclasses are containers for other entities.
137 /*virtual*/ bool EntityContainer::isContainer() const
143 * @return false: because entities made from this class
144 * and subclasses are containers for other entities.
146 /*virtual*/ bool EntityContainer::isAtomic() const
152 * Called when the undo state changed. Forwards the event to all sub-entities.
154 * @param undone true: entity has become invisible.
155 * false: entity has become visible.
157 void EntityContainer::undoStateChanged(bool undone)
159 Entity::undoStateChanged(undone);
161 // ! don't pass on to subentities. undo list handles them
163 /*for (Entity* e=firstEntity(RS2::ResolveNone);
165 e=nextEntity(RS2::ResolveNone)) {
166 e->setUndoState(undone);
170 void EntityContainer::setVisible(bool v)
172 DEBUG->print("EntityContainer::setVisible: %d", v);
173 Entity::setVisible(v);
176 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
178 DEBUG->print("EntityContainer::setVisible: subentity: %d", v);
184 * @return Total length of all entities in this container.
186 double EntityContainer::getLength()
190 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
194 double l = e->getLength();
212 * Selects this entity.
214 bool EntityContainer::setSelected(bool select)
216 // This entity's select:
217 if (Entity::setSelected(select))
219 // All sub-entity's select:
220 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
224 e->setSelected(select);
237 * Toggles select on this entity.
239 bool EntityContainer::toggleSelected()
241 // Toggle this entity's select:
242 if (Entity::toggleSelected())
245 // Toggle all sub-entity's select:
246 /*for (Entity* e=firstEntity(RS2::ResolveNone);
248 e=nextEntity(RS2::ResolveNone)) {
260 * Selects all entities within the given area.
262 * @param select True to select, False to deselect the entities.
264 void EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
268 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
274 if (e->isInWindow(v1, v2))
276 //e->setSelected(select);
279 else if (cross == true)
283 Line(NULL, LineData(v1, Vector(v2.x, v1.y))),
284 Line(NULL, LineData(Vector(v2.x, v1.y), v2)),
285 Line(NULL, LineData(v2, Vector(v1.x, v2.y))),
286 Line(NULL, LineData(Vector(v1.x, v2.y), v1))
290 if (e->isContainer())
292 EntityContainer * ec = (EntityContainer *)e;
294 for(Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false;
295 se=ec->nextEntity(RS2::ResolveAll))
297 for(int i=0; i<4; ++i)
299 sol = Information::getIntersection(se, &l[i], true);
311 for(int i=0; i<4; ++i)
313 sol = Information::getIntersection(e, &l[i], true);
327 e->setSelected(select);
333 * Adds a entity to this container and updates the borders of this
334 * entity-container if autoUpdateBorders is true.
336 void EntityContainer::addEntity(Entity * entity)
340 LayerList* lst = getDocument()->getLayerList();
342 Layer* l = lst->getActive();
343 if (l!=NULL && l->isLocked()) {
349 //printf("EntityContainer::addEntity(): entity=%08X\n", entity);
354 if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch)
355 entities.prepend(entity);
357 entities.append(entity);
359 if (autoUpdateBorders)
360 adjustBorders(entity);
361 //printf(" # of entities=%d\n", entities.size());
365 * Inserts a entity to this container at the given position and updates
366 * the borders of this entity-container if autoUpdateBorders is true.
368 void EntityContainer::insertEntity(int index, Entity * entity)
373 entities.insert(index, entity);
375 if (autoUpdateBorders)
376 adjustBorders(entity);
380 * Replaces the entity at the given index with the given entity
381 * and updates the borders of this entity-container if autoUpdateBorders is true.
383 void EntityContainer::replaceEntity(int index, Entity * entity)
388 entities.replace(index, entity);
390 if (autoUpdateBorders)
391 adjustBorders(entity);
395 * Removes an entity from this container and updates the borders of
396 * this entity-container if autoUpdateBorders is true.
398 bool EntityContainer::removeEntity(Entity * entity)
400 // bool ret = entities.remove(entity);
401 bool ret = (bool)entities.removeAll(entity);
403 if (autoUpdateBorders)
410 * Erases all entities in this container and resets the borders..
412 void EntityContainer::clear()
419 * Counts all entities (branches of the tree).
421 unsigned long int EntityContainer::count()
423 return entities.count();
427 * Counts all entities (leaves of the tree).
429 unsigned long int EntityContainer::countDeep()
431 unsigned long int c = 0;
433 for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
442 * Counts the selected entities in this container.
444 unsigned long int EntityContainer::countSelected()
446 unsigned long int c = 0;
448 for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
460 * Enables / disables automatic update of borders on entity removals
461 * and additions. By default this is turned on.
463 /*virtual*/ void EntityContainer::setAutoUpdateBorders(bool enable)
465 autoUpdateBorders = enable;
469 * Adjusts the borders of this graphic (max/min values)
471 void EntityContainer::adjustBorders(Entity * entity)
473 //DEBUG->print("EntityContainer::adjustBorders");
479 // make sure a container is not empty (otherwise the border
480 // would get extended to 0/0):
481 if (!entity->isContainer() || entity->count() > 0)
483 minV = Vector::minimum(entity->getMin(), minV);
484 maxV = Vector::maximum(entity->getMax(), maxV);
487 // Notify parents. The border for the parent might
488 // also change TODO: Check for efficiency
490 //parent->adjustBorders(this);
495 * Recalculates the borders of this entity container.
497 void EntityContainer::calculateBorders()
499 DEBUG->print("EntityContainer::calculateBorders");
503 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
505 Layer * layer = e->getLayer();
507 DEBUG->print("EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
509 if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
511 e->calculateBorders();
516 DEBUG->print("EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y);
518 // needed for correcting corrupt data (PLANS.dxf)
519 if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
520 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
526 if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
527 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
533 DEBUG->print("EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
535 //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
537 //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
538 //Entity::calculateBorders();
542 * Recalculates the borders of this entity container including
543 * invisible entities.
545 void EntityContainer::forcedCalculateBorders()
547 //DEBUG->print("EntityContainer::calculateBorders");
551 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
553 //Layer* layer = e->getLayer();
555 if (e->isContainer())
557 ((EntityContainer *)e)->forcedCalculateBorders();
561 e->calculateBorders();
567 // needed for correcting corrupt data (PLANS.dxf)
568 if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
569 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
575 if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
576 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
582 //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
584 //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
585 //Entity::calculateBorders();
589 * Updates all Dimension entities in this container and
590 * reposition their labels.
592 void EntityContainer::updateDimensions()
594 DEBUG->print("EntityContainer::updateDimensions()");
596 //for (Entity* e=firstEntity(RS2::ResolveNone);
598 // e=nextEntity(RS2::ResolveNone)) {
601 // Q3PtrListIterator<Entity> it = createIterator();
602 QListIterator<Entity *> it = createIterator();
603 // return QListIterator<Entity *>(entities);
607 while ((e = it.current()) != NULL)
611 if (Information::isDimension(e->rtti()))
613 // update and reposition label:
614 ((Dimension *)e)->update(true);
616 else if (e->isContainer())
618 ((EntityContainer *)e)->updateDimensions();
622 for(int i=0; i<entities.size(); i++)
624 Entity * e = entities[i];
626 if (Information::isDimension(e->rtti()))
627 // update and reposition label:
628 ((Dimension *)e)->update(true);
629 else if (e->isContainer())
630 ((EntityContainer *)e)->updateDimensions();
634 DEBUG->print("EntityContainer::updateDimensions() OK");
638 * Updates all Insert entities in this container.
640 void EntityContainer::updateInserts()
642 DEBUG->print("EntityContainer::updateInserts()");
644 //for (Entity* e=firstEntity(RS2::ResolveNone);
646 // e=nextEntity(RS2::ResolveNone)) {
648 Q3PtrListIterator<Entity> it = createIterator();
651 while ((e = it.current()) != NULL)
654 //// Only update our own inserts and not inserts of inserts
655 if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
657 ((Insert *)e)->update();
659 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
661 ((EntityContainer *)e)->updateInserts();
665 for(int i=0; i<entities.size(); i++)
667 Entity * e = entities[i];
669 //// Only update our own inserts and not inserts of inserts
670 if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/)
671 ((Insert *)e)->update();
672 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
673 ((EntityContainer *)e)->updateInserts();
677 DEBUG->print("EntityContainer::updateInserts() OK");
681 * Renames all inserts with name 'oldName' to 'newName'. This is
682 * called after a block was rename to update the inserts.
684 void EntityContainer::renameInserts(const QString& oldName, const QString& newName)
686 DEBUG->print("EntityContainer::renameInserts()");
688 //for (Entity* e=firstEntity(RS2::ResolveNone);
690 // e=nextEntity(RS2::ResolveNone)) {
693 Q3PtrListIterator<Entity> it = createIterator();
695 while ( (e = it.current()) != NULL ) {
698 if (e->rtti()==RS2::EntityInsert) {
699 Insert* i = ((Insert*)e);
700 if (i->getName()==oldName) {
703 } else if (e->isContainer()) {
704 ((EntityContainer*)e)->renameInserts(oldName, newName);
708 for(int i=0; i<entities.size(); i++)
710 Entity * e = entities[i];
712 if (e->rtti() == RS2::EntityInsert)
714 Insert * i = ((Insert *)e);
716 if (i->getName() == oldName)
719 else if (e->isContainer())
720 ((EntityContainer *)e)->renameInserts(oldName, newName);
724 DEBUG->print("EntityContainer::renameInserts() OK");
729 * Updates all Spline entities in this container.
731 void EntityContainer::updateSplines()
733 DEBUG->print("EntityContainer::updateSplines()");
735 //for (Entity* e=firstEntity(RS2::ResolveNone);
737 // e=nextEntity(RS2::ResolveNone)) {
739 Q3PtrListIterator<Entity> it = createIterator();
741 while ( (e = it.current()) != NULL ) {
743 //// Only update our own inserts and not inserts of inserts
744 if (e->rtti()==RS2::EntitySpline /*&& e->getParent()==this*/) {
745 ((Spline*)e)->update();
746 } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
747 ((EntityContainer*)e)->updateSplines();
751 for(int i=0; i<entities.size(); i++)
753 Entity * e = entities[i];
755 //// Only update our own inserts and not inserts of inserts
756 if (e->rtti() == RS2::EntitySpline /*&& e->getParent()==this*/)
757 ((Spline *)e)->update();
758 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
759 ((EntityContainer *)e)->updateSplines();
763 DEBUG->print("EntityContainer::updateSplines() OK");
767 * Updates the sub entities of this container.
769 void EntityContainer::update()
771 //for (Entity* e=firstEntity(RS2::ResolveNone);
773 // e=nextEntity(RS2::ResolveNone)) {
775 Q3PtrListIterator<Entity> it = createIterator();
777 while ( (e = it.current()) != NULL ) {
782 for(int i=0; i<entities.size(); i++)
784 // Entity * e = entities[i];
786 entities[i]->update();
792 * Returns the first entity or NULL if this graphic is empty.
795 Entity * EntityContainer::firstEntity(RS2::ResolveLevel level)
799 case RS2::ResolveNone:
800 // return entities.first();
801 // entityIterator.toFront();
802 entityIterator = entities;
803 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
806 case RS2::ResolveAllButInserts:
809 // Entity * e = entities.first();
810 // entityIterator.toFront();
811 entityIterator = entities;
812 Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
814 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
816 subContainer = (EntityContainer *)e;
817 e = ((EntityContainer *)e)->firstEntity(level);
823 e = nextEntity(level);
831 case RS2::ResolveAll:
834 // Entity * e = entities.first();
835 // entityIterator.toFront();
836 entityIterator = entities;
837 Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
839 if (e != NULL && e->isContainer())
841 subContainer = (EntityContainer *)e;
842 e = ((EntityContainer *)e)->firstEntity(level);
848 e = nextEntity(level);
861 * Returns the last entity or \p NULL if this graphic is empty.
863 * @param level \li \p 0 Groups are not resolved
864 * \li \p 1 (default) only Groups are resolved
865 * \li \p 2 all Entity Containers are resolved
867 Entity * EntityContainer::lastEntity(RS2::ResolveLevel level)
871 case RS2::ResolveNone:
872 // return entities.last();
873 entityIterator = entities;
874 entityIterator.toBack();
875 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
878 case RS2::ResolveAllButInserts:
880 // Entity * e = entities.last();
881 entityIterator = entities;
882 entityIterator.toBack();
883 Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
886 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
888 subContainer = (EntityContainer *)e;
889 e = ((EntityContainer *)e)->lastEntity(level);
896 case RS2::ResolveAll:
898 // Entity * e = entities.last();
899 entityIterator = entities;
900 entityIterator.toBack();
901 Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
904 if (e != NULL && e->isContainer())
906 subContainer = (EntityContainer *)e;
907 e = ((EntityContainer *)e)->lastEntity(level);
919 * Returns the next entity or container or \p NULL if the last entity
920 * returned by \p next() was the last entity in the container.
922 Entity * EntityContainer::nextEntity(RS2::ResolveLevel level)
926 case RS2::ResolveNone:
927 // return entities.next();
928 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
931 case RS2::ResolveAllButInserts:
935 if (subContainer != NULL)
937 e = subContainer->nextEntity(level);
945 // e = entities.next();
946 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
951 // e = entities.next();
952 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
955 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
957 subContainer = (EntityContainer *)e;
958 e = ((EntityContainer *)e)->firstEntity(level);
964 e = nextEntity(level);
972 case RS2::ResolveAll:
976 if (subContainer != NULL)
978 e = subContainer->nextEntity(level);
983 // e = entities.next();
984 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
988 // e = entities.next();
989 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
992 if (e != NULL && e->isContainer())
994 subContainer = (EntityContainer *)e;
995 e = ((EntityContainer *)e)->firstEntity(level);
1000 subContainer = NULL;
1001 e = nextEntity(level);
1013 * Returns the prev entity or container or \p NULL if the last entity
1014 * returned by \p prev() was the first entity in the container.
1016 Entity * EntityContainer::prevEntity(RS2::ResolveLevel level)
1022 case RS2::ResolveNone:
1023 // return entities.prev();
1024 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1027 case RS2::ResolveAllButInserts:
1030 if (subContainer != NULL)
1032 e = subContainer->prevEntity(level);
1037 // e = entities.prev();
1038 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1042 // e = entities.prev();
1043 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1046 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
1048 subContainer = (EntityContainer *)e;
1049 e = ((EntityContainer *)e)->lastEntity(level);
1054 subContainer = NULL;
1055 e = prevEntity(level);
1061 case RS2::ResolveAll:
1064 if (subContainer != NULL)
1066 e = subContainer->prevEntity(level);
1071 // e = entities.prev();
1072 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1076 // e = entities.prev();
1077 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1080 if (e != NULL && e->isContainer())
1082 subContainer = (EntityContainer *)e;
1083 e = ((EntityContainer *)e)->lastEntity(level);
1088 subContainer = NULL;
1089 e = prevEntity(level);
1100 * @return Entity at the given index or NULL if the index is out of range.
1102 Entity * EntityContainer::entityAt(uint index)
1104 return entities.at(index);
1108 * @return Current index.
1110 int EntityContainer::entityAt()
1112 #warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)"
1113 // return entities.at();
1118 * Finds the given entity and makes it the current entity if found.
1120 int EntityContainer::findEntity(Entity * entity)
1122 // return entities.find(entity);
1124 entityIterator.toFront();
1125 entityIterator.findNext(entity);
1127 return entities.indexOf(entity);
1131 * @return The current entity.
1133 Entity * EntityContainer::currentEntity()
1135 // return entities.current();
1137 // We really need to refactor this crap, this is the way it is now to support
1138 // the old broken way of doing things
1139 return entityIterator.peekNext();
1143 #warning "!!! Not needed anymore !!!"
1145 * Returns the copy to a new iterator for traversing the entities.
1147 //Q3PtrListIterator<Entity> EntityContainer::createIterator()
1148 QListIterator<Entity *> EntityContainer::createIterator()
1150 // return Q3PtrListIterator<Entity>(entities);
1151 return QListIterator<Entity *>(entities);
1155 /*virtual*/ bool EntityContainer::isEmpty()
1157 return (count() == 0);
1161 * @return The point which is closest to 'coord'
1162 * (one of the vertexes)
1164 Vector EntityContainer::getNearestEndpoint(const Vector & coord, double * dist)
1166 double minDist = RS_MAXDOUBLE; // minimum measured distance
1167 double curDist; // currently measured distance
1168 Vector closestPoint(false); // closest found endpoint
1169 Vector point; // endpoint found
1171 //Q3PtrListIterator<Entity> it = createIterator();
1173 //while ( (en = it.current()) != NULL ) {
1175 for (Entity* en = firstEntity();
1177 en = nextEntity()) {
1179 if (en->isVisible()) {
1180 point = en->getNearestEndpoint(coord, &curDist);
1181 if (point.valid && curDist<minDist) {
1182 closestPoint = point;
1191 return closestPoint;
1194 Vector EntityContainer::getNearestPointOnEntity(const Vector & coord,
1195 bool onEntity, double * dist, Entity ** entity)
1197 Vector point(false);
1199 Entity * e = getNearestEntity(coord, dist, RS2::ResolveNone);
1201 if (e && e->isVisible())
1202 point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1207 Vector EntityContainer::getNearestCenter(const Vector & coord, double * dist)
1209 Vector point(false);
1210 Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1213 point = closestEntity->getNearestCenter(coord, dist);
1218 Vector EntityContainer::getNearestMiddle(const Vector & coord, double * dist)
1220 Vector point(false);
1221 Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1224 point = closestEntity->getNearestMiddle(coord, dist);
1229 Vector EntityContainer::getNearestDist(double distance, const Vector & coord,
1232 Vector point(false);
1233 Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1236 point = closestEntity->getNearestDist(distance, coord, dist);
1242 * @return The intersection which is closest to 'coord'
1244 Vector EntityContainer::getNearestIntersection(const Vector & coord,
1247 double minDist = RS_MAXDOUBLE; // minimum measured distance
1248 double curDist; // currently measured distance
1249 Vector closestPoint(false); // closest found endpoint
1250 Vector point; // endpoint found
1251 VectorSolutions sol;
1252 Entity * closestEntity;
1254 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1258 for(Entity * en=firstEntity(RS2::ResolveAll); en!=NULL;
1259 en = nextEntity(RS2::ResolveAll))
1261 if (en->isVisible() && en!=closestEntity)
1263 sol = Information::getIntersection(closestEntity, en, true);
1265 for(int i=0; i<4; i++)
1271 curDist = coord.distanceTo(point);
1273 if (curDist < minDist)
1275 closestPoint = point;
1287 return closestPoint;
1290 Vector EntityContainer::getNearestRef(const Vector & coord, double * dist)
1292 double minDist = RS_MAXDOUBLE; // minimum measured distance
1293 double curDist; // currently measured distance
1294 Vector closestPoint(false); // closest found endpoint
1295 Vector point; // endpoint found
1297 for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1299 if (en->isVisible())
1301 point = en->getNearestRef(coord, &curDist);
1303 if (point.valid && curDist < minDist)
1305 closestPoint = point;
1314 return closestPoint;
1317 Vector EntityContainer::getNearestSelectedRef(const Vector & coord,
1320 double minDist = RS_MAXDOUBLE; // minimum measured distance
1321 double curDist; // currently measured distance
1322 Vector closestPoint(false); // closest found endpoint
1323 Vector point; // endpoint found
1325 for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1327 if (en->isVisible() && en->isSelected() && !en->isParentSelected())
1329 point = en->getNearestSelectedRef(coord, &curDist);
1331 if (point.valid && curDist < minDist)
1333 closestPoint = point;
1342 return closestPoint;
1345 double EntityContainer::getDistanceToPoint(const Vector & coord,
1346 Entity ** entity, RS2::ResolveLevel level, double solidDist)
1348 DEBUG->print("EntityContainer::getDistanceToPoint");
1350 double minDist = RS_MAXDOUBLE; // minimum measured distance
1351 double curDist; // currently measured distance
1352 Entity * closestEntity = NULL; // closest entity found
1353 Entity * subEntity = NULL;
1356 for(Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level))
1360 DEBUG->print("entity: getDistanceToPoint");
1361 DEBUG->print("entity: %d", e->rtti());
1362 curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1363 DEBUG->print("entity: getDistanceToPoint: OK");
1365 if (curDist<minDist)
1367 if (level != RS2::ResolveAll)
1370 closestEntity = subEntity;
1378 *entity = closestEntity;
1380 DEBUG->print("EntityContainer::getDistanceToPoint: OK");
1384 Entity * EntityContainer::getNearestEntity(const Vector & coord,
1385 double * dist, RS2::ResolveLevel level)
1387 DEBUG->print("EntityContainer::getNearestEntity");
1390 // distance for points inside solids:
1391 double solidDist = RS_MAXDOUBLE;
1396 double d = getDistanceToPoint(coord, &e, level, solidDist);
1398 if (e && e->isVisible() == false)
1401 // if d is negative, use the default distance (used for points inside solids)
1405 DEBUG->print("EntityContainer::getNearestEntity: OK");
1410 * Rearranges the atomic entities in this container in a way that connected
1411 * entities are stored in the right order and direction.
1412 * Non-recoursive. Only affects atomic entities in this container.
1414 * @retval true all contours were closed
1415 * @retval false at least one contour is not closed
1417 bool EntityContainer::optimizeContours()
1419 DEBUG->print("EntityContainer::optimizeContours");
1421 Vector current(false);
1422 Vector start(false);
1423 EntityContainer tmp;
1425 bool changed = false;
1428 for(uint ci=0; ci<count(); ++ci)
1430 Entity * e1=entityAt(ci);
1432 if (e1 && e1->isEdge() && !e1->isContainer() && !e1->isProcessed())
1434 AtomicEntity * ce = (AtomicEntity *)e1;
1436 // next contour start:
1437 ce->setProcessed(true);
1438 tmp.addEntity(ce->clone());
1439 current = ce->getEndpoint();
1440 start = ce->getStartpoint();
1442 // find all connected entities:
1448 for(uint ei=0; ei<count(); ++ei)
1450 Entity * e2=entityAt(ei);
1452 if (e2 != NULL && e2->isEdge() && !e2->isContainer() &&
1455 AtomicEntity * e = (AtomicEntity *)e2;
1457 if (e->getStartpoint().distanceTo(current) < 1.0e-4)
1459 e->setProcessed(true);
1460 tmp.addEntity(e->clone());
1461 current = e->getEndpoint();
1464 else if (e->getEndpoint().distanceTo(current) < 1.0e-4)
1466 e->setProcessed(true);
1467 AtomicEntity * cl = (AtomicEntity *)e->clone();
1470 current = cl->getEndpoint();
1482 if (current.distanceTo(start) > 1.0e-4)
1487 // remove all atomic entities:
1494 for(Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1496 if (!en->isContainer())
1506 // add new sorted entities:
1507 for(Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity())
1509 en->setProcessed(false);
1510 addEntity(en->clone());
1513 DEBUG->print("EntityContainer::optimizeContours: OK");
1517 bool EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2)
1519 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1521 if (e->hasEndpointsWithinWindow(v1, v2))
1528 void EntityContainer::move(Vector offset)
1530 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1533 if (autoUpdateBorders)
1537 void EntityContainer::rotate(Vector center, double angle)
1539 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1540 e->rotate(center, angle);
1542 if (autoUpdateBorders)
1546 void EntityContainer::scale(Vector center, Vector factor)
1548 if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE)
1550 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1551 e->scale(center, factor);
1554 if (autoUpdateBorders)
1558 void EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2)
1560 if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6)
1562 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1563 e->mirror(axisPoint1, axisPoint2);
1567 void EntityContainer::stretch(Vector firstCorner, Vector secondCorner,
1570 if (getMin().isInWindow(firstCorner, secondCorner) &&
1571 getMax().isInWindow(firstCorner, secondCorner))
1577 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1578 e->stretch(firstCorner, secondCorner, offset);
1581 // some entitiycontainers might need an update (e.g. Leader):
1585 void EntityContainer::moveRef(const Vector & ref, const Vector & offset)
1587 for(Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1588 e->moveRef(ref, offset);
1590 if (autoUpdateBorders)
1594 void EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1596 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1597 e->moveSelectedRef(ref, offset);
1599 if (autoUpdateBorders)
1603 void EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
1605 if (!painter || !view)
1608 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1611 if (e->rtti() == RS2::EntityText)
1613 std::cout << "About to draw TEXT entity... "
1614 << "TEXT=\"" << ((Text *)e)->getText().toAscii().data() << "\"" << std::endl;
1616 //OK, we have text, but no insert entities at least none that are drawn...
1617 //Ah! But with a standard text entity, it DOES have them!
1618 else if (e->rtti() == RS2::EntityInsert)
1620 std::cout << "About to draw INSERT entity... "
1621 << "INSERT=\"" << ((Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl;
1624 view->drawEntity(e);
1631 * Dumps the entities to stdout.
1633 std::ostream & operator<<(std::ostream & os, EntityContainer & ec)
1635 static int indent = 0;
1636 char * tab = new char[indent * 2 + 1];
1638 for(int i=0; i<indent*2; i++)
1641 tab[indent * 2] = '\0';
1643 unsigned long int id = ec.getId();
1645 os << tab << "EntityContainer[" << id << "]: \n";
1646 os << tab << "Borders[" << id << "]: "
1647 << ec.minV << " - " << ec.maxV << "\n";
1648 //os << tab << "Unit[" << id << "]: "
1649 //<< Units::unit2string (ec.unit) << "\n";
1652 os << tab << "Layer[" << id << "]: "
1653 << ec.getLayer()->getName().toLatin1().data() << "\n";
1657 os << tab << "Layer[" << id << "]: <NULL>\n";
1659 //os << ec.layerList << "\n";
1661 os << tab << " Flags[" << id << "]: "
1662 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1663 os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1664 os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1667 os << tab << "Entities[" << id << "]: \n";
1670 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1671 for(int i=0; i<ec.entities.size(); i++)
1673 Entity * t = ec.entities[i];
1674 s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1675 os << s.toAscii().data();
1677 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1678 os << s.toAscii().data();
1680 for(Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1684 case RS2::EntityInsert:
1685 os << tab << *((Insert *)t);
1686 os << tab << *((Entity *)t);
1687 os << tab << *((EntityContainer *)t);
1690 if (t->isContainer())
1691 os << tab << *((EntityContainer *)t);
1699 os << tab << "\n\n";