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 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_entitycontainer.h"
18 #include "rs_dimension.h"
22 #include "rs_polyline.h"
24 #include "rs_insert.h"
25 #include "rs_spline.h"
26 #include "rs_information.h"
27 #include "rs_graphicview.h"
28 #include "paintintf.h"
30 bool RS_EntityContainer::autoUpdateBorders = true;
33 * Default constructor.
35 * @param owner True if we own and also delete the entities.
37 RS_EntityContainer::RS_EntityContainer(RS_EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
38 RS_Entity(parent), entityIterator(entities)
39 //NOTE: This constructor may not be explicitly OR implicitly called, meaning that
40 // entityIterator will not get initialized!
42 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
43 // entities.setAutoDelete(owner);
44 RS_DEBUG->print("RS_EntityContainer::RS_EntityContainer: owner: %d", (int)owner);
46 //autoUpdateBorders = true;
50 * Copy constructor. Makes a deep copy of all entities.
53 RS_EntityContainer::RS_EntityContainer(const RS_EntityContainer& ec)
62 RS_EntityContainer::~RS_EntityContainer()
67 RS_Entity * RS_EntityContainer::clone()
69 // RS_DEBUG->print("RS_EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
70 RS_EntityContainer * ec = new RS_EntityContainer(*this);
71 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
72 // ec->entities.setAutoDelete(entities.autoDelete());
73 // RS_DEBUG->print("RS_EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete());
81 * Detaches shallow copies and creates deep copies of all subentities.
82 * This is called after cloning entity containers.
84 void RS_EntityContainer::detach()
86 // Q3PtrList<RS_Entity> tmp;
87 QList<RS_Entity *> tmp;
88 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
89 // bool autoDel = entities.autoDelete();
90 // RS_DEBUG->print("RS_EntityContainer::detach: autoDel: %d", (int)autoDel);
91 // entities.setAutoDelete(false);
93 // make deep copies of all entities:
94 for(RS_Entity * e=firstEntity(); e!=NULL; e=nextEntity())
96 if (!e->getFlag(RS2::FlagTemp))
98 tmp.append(e->clone());
102 // clear shared pointers:
104 // entities.setAutoDelete(autoDel);
106 // point to new deep copies:
107 // for(RS_Entity * e=tmp.first(); e!=NULL; e=tmp.next())
108 for(int i=0; i<tmp.size(); i++)
110 RS_Entity * e = tmp[i];
116 /** @return RS2::EntityContainer */
117 /*virtual*/ RS2::EntityType RS_EntityContainer::rtti() const
119 return RS2::EntityContainer;
122 void RS_EntityContainer::reparent(RS_EntityContainer * parent)
124 RS_Entity::reparent(parent);
127 for(RS_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 RS_EntityContainer::isContainer() const
143 * @return false: because entities made from this class
144 * and subclasses are containers for other entities.
146 /*virtual*/ bool RS_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 RS_EntityContainer::undoStateChanged(bool undone)
159 RS_Entity::undoStateChanged(undone);
161 // ! don't pass on to subentities. undo list handles them
163 /*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
165 e=nextEntity(RS2::ResolveNone)) {
166 e->setUndoState(undone);
170 void RS_EntityContainer::setVisible(bool v)
172 RS_DEBUG->print("RS_EntityContainer::setVisible: %d", v);
173 RS_Entity::setVisible(v);
176 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
178 RS_DEBUG->print("RS_EntityContainer::setVisible: subentity: %d", v);
184 * @return Total length of all entities in this container.
186 double RS_EntityContainer::getLength()
190 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
194 double l = e->getLength();
212 * Selects this entity.
214 bool RS_EntityContainer::setSelected(bool select)
216 // This entity's select:
217 if (RS_Entity::setSelected(select))
219 // All sub-entity's select:
220 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
224 e->setSelected(select);
237 * Toggles select on this entity.
239 bool RS_EntityContainer::toggleSelected()
241 // Toggle this entity's select:
242 if (RS_Entity::toggleSelected())
245 // Toggle all sub-entity's select:
246 /*for (RS_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 RS_EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
268 for(RS_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 RS_Line(NULL, RS_LineData(v1, Vector(v2.x, v1.y))),
284 RS_Line(NULL, RS_LineData(Vector(v2.x, v1.y), v2)),
285 RS_Line(NULL, RS_LineData(v2, Vector(v1.x, v2.y))),
286 RS_Line(NULL, RS_LineData(Vector(v1.x, v2.y), v1))
290 if (e->isContainer())
292 RS_EntityContainer * ec = (RS_EntityContainer *)e;
294 for(RS_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 = RS_Information::getIntersection(se, &l[i], true);
311 for(int i=0; i<4; ++i)
313 sol = RS_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 RS_EntityContainer::addEntity(RS_Entity * entity)
340 RS_LayerList* lst = getDocument()->getLayerList();
342 RS_Layer* l = lst->getActive();
343 if (l!=NULL && l->isLocked()) {
349 //printf("RS_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 RS_EntityContainer::insertEntity(int index, RS_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 RS_EntityContainer::replaceEntity(int index, RS_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 RS_EntityContainer::removeEntity(RS_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 RS_EntityContainer::clear()
419 * Counts all entities (branches of the tree).
421 unsigned long int RS_EntityContainer::count()
423 return entities.count();
427 * Counts all entities (leaves of the tree).
429 unsigned long int RS_EntityContainer::countDeep()
431 unsigned long int c = 0;
433 for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
442 * Counts the selected entities in this container.
444 unsigned long int RS_EntityContainer::countSelected()
446 unsigned long int c = 0;
448 for(RS_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 RS_EntityContainer::setAutoUpdateBorders(bool enable)
465 autoUpdateBorders = enable;
469 * Adjusts the borders of this graphic (max/min values)
471 void RS_EntityContainer::adjustBorders(RS_Entity * entity)
473 //RS_DEBUG->print("RS_EntityContainer::adjustBorders");
478 // make sure a container is not empty (otherwise the border
479 // would get extended to 0/0):
480 if (!entity->isContainer() || entity->count() > 0)
482 minV = Vector::minimum(entity->getMin(), minV);
483 maxV = Vector::maximum(entity->getMax(), maxV);
486 // Notify parents. The border for the parent might
487 // also change TODO: Check for efficiency
489 //parent->adjustBorders(this);
495 * Recalculates the borders of this entity container.
497 void RS_EntityContainer::calculateBorders()
499 RS_DEBUG->print("RS_EntityContainer::calculateBorders");
503 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
505 RS_Layer * layer = e->getLayer();
507 RS_DEBUG->print("RS_EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
509 if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
511 e->calculateBorders();
516 RS_DEBUG->print("RS_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 RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
535 //RS_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 //RS_Entity::calculateBorders();
542 * Recalculates the borders of this entity container including
543 * invisible entities.
545 void RS_EntityContainer::forcedCalculateBorders()
547 //RS_DEBUG->print("RS_EntityContainer::calculateBorders");
551 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
553 //RS_Layer* layer = e->getLayer();
555 if (e->isContainer())
557 ((RS_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 //RS_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 //RS_Entity::calculateBorders();
589 * Updates all Dimension entities in this container and
590 * reposition their labels.
592 void RS_EntityContainer::updateDimensions()
594 RS_DEBUG->print("RS_EntityContainer::updateDimensions()");
596 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
598 // e=nextEntity(RS2::ResolveNone)) {
601 // Q3PtrListIterator<RS_Entity> it = createIterator();
602 QListIterator<RS_Entity *> it = createIterator();
603 // return QListIterator<RS_Entity *>(entities);
607 while ((e = it.current()) != NULL)
611 if (RS_Information::isDimension(e->rtti()))
613 // update and reposition label:
614 ((RS_Dimension *)e)->update(true);
616 else if (e->isContainer())
618 ((RS_EntityContainer *)e)->updateDimensions();
622 for(int i=0; i<entities.size(); i++)
624 RS_Entity * e = entities[i];
626 if (RS_Information::isDimension(e->rtti()))
627 // update and reposition label:
628 ((RS_Dimension *)e)->update(true);
629 else if (e->isContainer())
630 ((RS_EntityContainer *)e)->updateDimensions();
634 RS_DEBUG->print("RS_EntityContainer::updateDimensions() OK");
638 * Updates all Insert entities in this container.
640 void RS_EntityContainer::updateInserts()
642 RS_DEBUG->print("RS_EntityContainer::updateInserts()");
644 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
646 // e=nextEntity(RS2::ResolveNone)) {
648 Q3PtrListIterator<RS_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 ((RS_Insert *)e)->update();
659 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
661 ((RS_EntityContainer *)e)->updateInserts();
665 for(int i=0; i<entities.size(); i++)
667 RS_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 ((RS_Insert *)e)->update();
672 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
673 ((RS_EntityContainer *)e)->updateInserts();
677 RS_DEBUG->print("RS_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 RS_EntityContainer::renameInserts(const QString& oldName, const QString& newName)
686 RS_DEBUG->print("RS_EntityContainer::renameInserts()");
688 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
690 // e=nextEntity(RS2::ResolveNone)) {
693 Q3PtrListIterator<RS_Entity> it = createIterator();
695 while ( (e = it.current()) != NULL ) {
698 if (e->rtti()==RS2::EntityInsert) {
699 RS_Insert* i = ((RS_Insert*)e);
700 if (i->getName()==oldName) {
703 } else if (e->isContainer()) {
704 ((RS_EntityContainer*)e)->renameInserts(oldName, newName);
708 for(int i=0; i<entities.size(); i++)
710 RS_Entity * e = entities[i];
712 if (e->rtti() == RS2::EntityInsert)
714 RS_Insert * i = ((RS_Insert *)e);
716 if (i->getName() == oldName)
719 else if (e->isContainer())
720 ((RS_EntityContainer *)e)->renameInserts(oldName, newName);
724 RS_DEBUG->print("RS_EntityContainer::renameInserts() OK");
729 * Updates all Spline entities in this container.
731 void RS_EntityContainer::updateSplines()
733 RS_DEBUG->print("RS_EntityContainer::updateSplines()");
735 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
737 // e=nextEntity(RS2::ResolveNone)) {
739 Q3PtrListIterator<RS_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 ((RS_Spline*)e)->update();
746 } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
747 ((RS_EntityContainer*)e)->updateSplines();
751 for(int i=0; i<entities.size(); i++)
753 RS_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 ((RS_Spline *)e)->update();
758 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
759 ((RS_EntityContainer *)e)->updateSplines();
763 RS_DEBUG->print("RS_EntityContainer::updateSplines() OK");
767 * Updates the sub entities of this container.
769 void RS_EntityContainer::update()
771 //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
773 // e=nextEntity(RS2::ResolveNone)) {
775 Q3PtrListIterator<RS_Entity> it = createIterator();
777 while ( (e = it.current()) != NULL ) {
782 for(int i=0; i<entities.size(); i++)
784 // RS_Entity * e = entities[i];
786 entities[i]->update();
792 * Returns the first entity or NULL if this graphic is empty.
795 RS_Entity * RS_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 // RS_Entity * e = entities.first();
810 // entityIterator.toFront();
811 entityIterator = entities;
812 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
814 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
816 subContainer = (RS_EntityContainer *)e;
817 e = ((RS_EntityContainer *)e)->firstEntity(level);
823 e = nextEntity(level);
831 case RS2::ResolveAll:
834 // RS_Entity * e = entities.first();
835 // entityIterator.toFront();
836 entityIterator = entities;
837 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
839 if (e != NULL && e->isContainer())
841 subContainer = (RS_EntityContainer *)e;
842 e = ((RS_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 RS_Entity * RS_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 // RS_Entity * e = entities.last();
881 entityIterator = entities;
882 entityIterator.toBack();
883 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
886 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
888 subContainer = (RS_EntityContainer *)e;
889 e = ((RS_EntityContainer *)e)->lastEntity(level);
896 case RS2::ResolveAll:
898 // RS_Entity * e = entities.last();
899 entityIterator = entities;
900 entityIterator.toBack();
901 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
904 if (e != NULL && e->isContainer())
906 subContainer = (RS_EntityContainer *)e;
907 e = ((RS_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 RS_Entity * RS_EntityContainer::nextEntity(RS2::ResolveLevel level)
926 case RS2::ResolveNone:
927 // return entities.next();
928 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
931 case RS2::ResolveAllButInserts:
933 RS_Entity * e = NULL;
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 = (RS_EntityContainer *)e;
958 e = ((RS_EntityContainer *)e)->firstEntity(level);
964 e = nextEntity(level);
972 case RS2::ResolveAll:
974 RS_Entity * e = NULL;
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 = (RS_EntityContainer *)e;
995 e = ((RS_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 RS_Entity * RS_EntityContainer::prevEntity(RS2::ResolveLevel level)
1018 RS_Entity * e = NULL;
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 = (RS_EntityContainer *)e;
1049 e = ((RS_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 = (RS_EntityContainer *)e;
1083 e = ((RS_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 RS_Entity * RS_EntityContainer::entityAt(uint index)
1104 return entities.at(index);
1108 * @return Current index.
1110 int RS_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 RS_EntityContainer::findEntity(RS_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 RS_Entity * RS_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<RS_Entity> RS_EntityContainer::createIterator()
1148 QListIterator<RS_Entity *> RS_EntityContainer::createIterator()
1150 // return Q3PtrListIterator<RS_Entity>(entities);
1151 return QListIterator<RS_Entity *>(entities);
1155 /*virtual*/ bool RS_EntityContainer::isEmpty()
1157 return (count() == 0);
1161 * @return The point which is closest to 'coord'
1162 * (one of the vertexes)
1164 Vector RS_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<RS_Entity> it = createIterator();
1173 //while ( (en = it.current()) != NULL ) {
1175 for (RS_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;
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!=NULL && e->isVisible()) {
1204 point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1212 Vector RS_EntityContainer::getNearestCenter(const Vector& coord,
1215 Vector point(false);
1216 RS_Entity* closestEntity;
1218 //closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1219 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1221 if (closestEntity!=NULL) {
1222 point = closestEntity->getNearestCenter(coord, dist);
1230 Vector RS_EntityContainer::getNearestMiddle(const Vector& coord,
1233 Vector point(false);
1234 RS_Entity* closestEntity;
1236 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1238 if (closestEntity!=NULL) {
1239 point = closestEntity->getNearestMiddle(coord, dist);
1246 double minDist = RS_MAXDOUBLE; // minimum measured distance
1247 double curDist; // currently measured distance
1248 Vector closestPoint; // closest found endpoint
1249 Vector point; // endpoint found
1251 for (RS_Entity* en = firstEntity();
1253 en = nextEntity()) {
1255 if (en->isVisible()) {
1256 point = en->getNearestMiddle(coord, &curDist);
1257 if (curDist<minDist) {
1258 closestPoint = point;
1267 return closestPoint;
1273 Vector RS_EntityContainer::getNearestDist(double distance,
1274 const Vector& coord,
1277 Vector point(false);
1278 RS_Entity* closestEntity;
1280 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1282 if (closestEntity!=NULL) {
1283 point = closestEntity->getNearestDist(distance, coord, dist);
1292 * @return The intersection which is closest to 'coord'
1294 Vector RS_EntityContainer::getNearestIntersection(const Vector& coord,
1297 double minDist = RS_MAXDOUBLE; // minimum measured distance
1298 double curDist; // currently measured distance
1299 Vector closestPoint(false); // closest found endpoint
1300 Vector point; // endpoint found
1301 VectorSolutions sol;
1302 RS_Entity* closestEntity;
1304 closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1306 if (closestEntity!=NULL) {
1307 for (RS_Entity* en = firstEntity(RS2::ResolveAll);
1309 en = nextEntity(RS2::ResolveAll)) {
1311 if (en->isVisible() && en!=closestEntity) {
1312 sol = RS_Information::getIntersection(closestEntity,
1316 for (int i=0; i<4; i++) {
1319 curDist = coord.distanceTo(point);
1321 if (curDist<minDist) {
1322 closestPoint = point;
1335 return closestPoint;
1340 Vector RS_EntityContainer::getNearestRef(const Vector& coord,
1343 double minDist = RS_MAXDOUBLE; // minimum measured distance
1344 double curDist; // currently measured distance
1345 Vector closestPoint(false); // closest found endpoint
1346 Vector point; // endpoint found
1348 for (RS_Entity* en = firstEntity();
1350 en = nextEntity()) {
1352 if (en->isVisible()) {
1353 point = en->getNearestRef(coord, &curDist);
1354 if (point.valid && curDist<minDist) {
1355 closestPoint = point;
1364 return closestPoint;
1368 Vector RS_EntityContainer::getNearestSelectedRef(const Vector& coord,
1371 double minDist = RS_MAXDOUBLE; // minimum measured distance
1372 double curDist; // currently measured distance
1373 Vector closestPoint(false); // closest found endpoint
1374 Vector point; // endpoint found
1376 for (RS_Entity* en = firstEntity();
1378 en = nextEntity()) {
1380 if (en->isVisible() && en->isSelected() && !en->isParentSelected()) {
1381 point = en->getNearestSelectedRef(coord, &curDist);
1382 if (point.valid && curDist<minDist) {
1383 closestPoint = point;
1392 return closestPoint;
1396 double RS_EntityContainer::getDistanceToPoint(const Vector& coord,
1398 RS2::ResolveLevel level,
1401 RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint");
1403 double minDist = RS_MAXDOUBLE; // minimum measured distance
1404 double curDist; // currently measured distance
1405 RS_Entity* closestEntity = NULL; // closest entity found
1406 RS_Entity* subEntity = NULL;
1409 for (RS_Entity* e = firstEntity(level);
1411 e = nextEntity(level)) {
1413 if (e->isVisible()) {
1414 RS_DEBUG->print("entity: getDistanceToPoint");
1415 RS_DEBUG->print("entity: %d", e->rtti());
1416 curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1418 RS_DEBUG->print("entity: getDistanceToPoint: OK");
1420 if (curDist<minDist) {
1421 if (level!=RS2::ResolveAll) {
1424 closestEntity = subEntity;
1432 *entity = closestEntity;
1434 RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK");
1441 RS_Entity* RS_EntityContainer::getNearestEntity(const Vector& coord,
1443 RS2::ResolveLevel level) {
1445 RS_DEBUG->print("RS_EntityContainer::getNearestEntity");
1447 RS_Entity* e = NULL;
1449 // distance for points inside solids:
1450 double solidDist = RS_MAXDOUBLE;
1455 double d = getDistanceToPoint(coord, &e, level, solidDist);
1457 if (e!=NULL && e->isVisible()==false) {
1461 // if d is negative, use the default distance (used for points inside solids)
1465 RS_DEBUG->print("RS_EntityContainer::getNearestEntity: OK");
1473 * Rearranges the atomic entities in this container in a way that connected
1474 * entities are stored in the right order and direction.
1475 * Non-recoursive. Only affects atomic entities in this container.
1477 * @retval true all contours were closed
1478 * @retval false at least one contour is not closed
1480 bool RS_EntityContainer::optimizeContours() {
1482 RS_DEBUG->print("RS_EntityContainer::optimizeContours");
1484 Vector current(false);
1485 Vector start(false);
1486 RS_EntityContainer tmp;
1488 bool changed = false;
1491 for (uint ci=0; ci<count(); ++ci) {
1492 RS_Entity* e1=entityAt(ci);
1494 if (e1!=NULL && e1->isEdge() && !e1->isContainer() &&
1495 !e1->isProcessed()) {
1497 RS_AtomicEntity* ce = (RS_AtomicEntity*)e1;
1499 // next contour start:
1500 ce->setProcessed(true);
1501 tmp.addEntity(ce->clone());
1502 current = ce->getEndpoint();
1503 start = ce->getStartpoint();
1505 // find all connected entities:
1509 for (uint ei=0; ei<count(); ++ei) {
1510 RS_Entity* e2=entityAt(ei);
1512 if (e2!=NULL && e2->isEdge() && !e2->isContainer() &&
1513 !e2->isProcessed()) {
1515 RS_AtomicEntity* e = (RS_AtomicEntity*)e2;
1517 if (e->getStartpoint().distanceTo(current) <
1520 e->setProcessed(true);
1521 tmp.addEntity(e->clone());
1522 current = e->getEndpoint();
1525 } else if (e->getEndpoint().distanceTo(current) <
1528 e->setProcessed(true);
1529 RS_AtomicEntity* cl = (RS_AtomicEntity*)e->clone();
1532 current = cl->getEndpoint();
1544 if (current.distanceTo(start)>1.0e-4) {
1550 // remove all atomic entities:
1554 for (RS_Entity* en=firstEntity(); en!=NULL; en=nextEntity()) {
1555 if (!en->isContainer()) {
1563 // add new sorted entities:
1564 for (RS_Entity* en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) {
1565 en->setProcessed(false);
1566 addEntity(en->clone());
1569 RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
1574 bool RS_EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2) {
1575 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1577 e=nextEntity(RS2::ResolveNone)) {
1578 if (e->hasEndpointsWithinWindow(v1, v2)) {
1587 void RS_EntityContainer::move(Vector offset) {
1588 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1590 e=nextEntity(RS2::ResolveNone)) {
1593 if (autoUpdateBorders) {
1600 void RS_EntityContainer::rotate(Vector center, double angle) {
1601 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1603 e=nextEntity(RS2::ResolveNone)) {
1604 e->rotate(center, angle);
1606 if (autoUpdateBorders) {
1613 void RS_EntityContainer::scale(Vector center, Vector factor) {
1614 if (fabs(factor.x)>RS_TOLERANCE && fabs(factor.y)>RS_TOLERANCE) {
1615 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1617 e=nextEntity(RS2::ResolveNone)) {
1618 e->scale(center, factor);
1621 if (autoUpdateBorders) {
1628 void RS_EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2) {
1629 if (axisPoint1.distanceTo(axisPoint2)>1.0e-6) {
1630 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1632 e=nextEntity(RS2::ResolveNone)) {
1633 e->mirror(axisPoint1, axisPoint2);
1639 void RS_EntityContainer::stretch(Vector firstCorner,
1640 Vector secondCorner,
1643 if (getMin().isInWindow(firstCorner, secondCorner) &&
1644 getMax().isInWindow(firstCorner, secondCorner)) {
1648 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1650 e=nextEntity(RS2::ResolveNone)) {
1651 e->stretch(firstCorner, secondCorner, offset);
1655 // some entitiycontainers might need an update (e.g. RS_Leader):
1661 void RS_EntityContainer::moveRef(const Vector& ref,
1662 const Vector& offset) {
1664 for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1666 e=nextEntity(RS2::ResolveNone)) {
1667 e->moveRef(ref, offset);
1669 if (autoUpdateBorders) {
1674 void RS_EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1676 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1677 e->moveSelectedRef(ref, offset);
1679 if (autoUpdateBorders)
1683 //void RS_EntityContainer::draw(RS_Painter* painter, RS_GraphicView* view,
1684 void RS_EntityContainer::draw(PaintInterface * painter, RS_GraphicView * view, double /*patternOffset*/)
1686 if (painter == NULL || view == NULL)
1689 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone))
1690 view->drawEntity(e);
1694 * Dumps the entities to stdout.
1696 std::ostream & operator<<(std::ostream & os, RS_EntityContainer & ec)
1698 static int indent = 0;
1700 char * tab = new char[indent * 2 + 1];
1702 for(int i=0; i<indent*2; ++i)
1705 tab[indent * 2] = '\0';
1709 unsigned long int id = ec.getId();
1711 os << tab << "EntityContainer[" << id << "]: \n";
1712 os << tab << "Borders[" << id << "]: "
1713 << ec.minV << " - " << ec.maxV << "\n";
1714 //os << tab << "Unit[" << id << "]: "
1715 //<< RS_Units::unit2string (ec.unit) << "\n";
1716 if (ec.getLayer() != NULL)
1718 os << tab << "Layer[" << id << "]: "
1719 << ec.getLayer()->getName().toLatin1().data() << "\n";
1723 os << tab << "Layer[" << id << "]: <NULL>\n";
1725 //os << ec.layerList << "\n";
1727 os << tab << " Flags[" << id << "]: "
1728 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1729 os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1730 os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1733 os << tab << "Entities[" << id << "]: \n";
1736 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1737 for(int i=0; i<ec.entities.size(); i++)
1739 RS_Entity * t = ec.entities[i];
1740 s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1741 os << s.toAscii().data();
1743 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1744 os << s.toAscii().data();
1746 for(RS_Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1750 case RS2::EntityInsert:
1751 os << tab << *((RS_Insert *)t);
1752 os << tab << *((RS_Entity *)t);
1753 os << tab << *((RS_EntityContainer *)t);
1756 if (t->isContainer())
1757 os << tab << *((RS_EntityContainer *)t);
1765 os << tab << "\n\n";