X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fbase%2Fentitycontainer.cpp;fp=src%2Fbase%2Fentitycontainer.cpp;h=0000000000000000000000000000000000000000;hb=9f6ad3fe0b9cb30115a5d38e8af3aebed0d70c08;hp=dc247e76ba736cce38e44cdb1201b0a927aed9c4;hpb=43c13b052d069ba435277d93867380d00c04931f;p=architektonas diff --git a/src/base/entitycontainer.cpp b/src/base/entitycontainer.cpp deleted file mode 100644 index dc247e7..0000000 --- a/src/base/entitycontainer.cpp +++ /dev/null @@ -1,1704 +0,0 @@ -// entitycontainer.cpp -// -// Part of the Architektonas Project -// Originally part of QCad Community Edition by Andrew Mustun -// Extensively rewritten and refactored by James L. Hammons -// Portions copyright (C) 2001-2003 RibbonSoft -// Copyright (C) 2010 Underground Software -// See the README and GPLv2 files for licensing and warranty information -// -// JLH = James L. Hammons -// -// Who When What -// --- ---------- ----------------------------------------------------------- -// JLH 05/28/2010 Added this text. :-) -// - -#include "entitycontainer.h" - -#include "debug.h" -#include "dimension.h" -#include "mathextra.h" -#include "layer.h" -#include "line.h" -#include "polyline.h" -#include "text.h" -#include "insert.h" -#include "spline.h" -#include "information.h" -#include "graphicview.h" -#include "paintinterface.h" - -bool EntityContainer::autoUpdateBorders = true; - -/** - * Default constructor. - * - * @param owner True if we own and also delete the entities. - */ -EntityContainer::EntityContainer(EntityContainer * parent/*= NULL*/, bool owner/*= true*/): - Entity(parent), entityIterator(entities) -//NOTE: This constructor may not be explicitly OR implicitly called, meaning that -// entityIterator will not get initialized! -{ -#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!" -// entities.setAutoDelete(owner); - DEBUG->print("EntityContainer::EntityContainer: owner: %d", (int)owner); - subContainer = NULL; - //autoUpdateBorders = true; -} - -/** - * Copy constructor. Makes a deep copy of all entities. - */ -/* -EntityContainer::EntityContainer(const EntityContainer& ec) - : Entity(ec) -{ -} -*/ - -/** - * Destructor. - */ -EntityContainer::~EntityContainer() -{ - clear(); -} - -Entity * EntityContainer::clone() -{ -// DEBUG->print("EntityContainer::clone: ori autoDel: %d", entities.autoDelete()); - EntityContainer * ec = new EntityContainer(*this); -#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!" -// ec->entities.setAutoDelete(entities.autoDelete()); -// DEBUG->print("EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete()); - ec->detach(); - ec->initId(); - - return ec; -} - -/** - * Detaches shallow copies and creates deep copies of all subentities. - * This is called after cloning entity containers. - */ -void EntityContainer::detach() -{ -// Q3PtrList tmp; - QList tmp; -#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!" -// bool autoDel = entities.autoDelete(); -// DEBUG->print("EntityContainer::detach: autoDel: %d", (int)autoDel); -// entities.setAutoDelete(false); - - // make deep copies of all entities: - for(Entity * e=firstEntity(); e!=NULL; e=nextEntity()) - { - if (!e->getFlag(RS2::FlagTemp)) - { - tmp.append(e->clone()); - } - } - - // clear shared pointers: - entities.clear(); -// entities.setAutoDelete(autoDel); - - // point to new deep copies: -// for(Entity * e=tmp.first(); e!=NULL; e=tmp.next()) - for(int i=0; ireparent(this); - } -} - -/** @return RS2::EntityContainer */ -/*virtual*/ RS2::EntityType EntityContainer::rtti() const -{ - return RS2::EntityContainer; -} - -void EntityContainer::reparent(EntityContainer * parent) -{ - Entity::reparent(parent); - - // All sub-entities: - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->reparent(parent); -} - -/** - * @return true: because entities made from this class - * and subclasses are containers for other entities. - */ -/*virtual*/ bool EntityContainer::isContainer() const -{ - return true; -} - -/** - * @return false: because entities made from this class - * and subclasses are containers for other entities. - */ -/*virtual*/ bool EntityContainer::isAtomic() const -{ - return false; -} - -/** - * Called when the undo state changed. Forwards the event to all sub-entities. - * - * @param undone true: entity has become invisible. - * false: entity has become visible. - */ -void EntityContainer::undoStateChanged(bool undone) -{ - Entity::undoStateChanged(undone); - - // ! don't pass on to subentities. undo list handles them - // All sub-entities: - /*for (Entity* e=firstEntity(RS2::ResolveNone); - e!=NULL; - e=nextEntity(RS2::ResolveNone)) { - e->setUndoState(undone); -}*/ -} - -void EntityContainer::setVisible(bool v) -{ - DEBUG->print("EntityContainer::setVisible: %d", v); - Entity::setVisible(v); - - // All sub-entities: - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - DEBUG->print("EntityContainer::setVisible: subentity: %d", v); - e->setVisible(v); - } -} - -/** - * @return Total length of all entities in this container. - */ -double EntityContainer::getLength() -{ - double ret = 0.0; - - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - if (e->isVisible()) - { - double l = e->getLength(); - - if (l < 0.0) - { - ret = -1.0; - break; - } - else - { - ret += l; - } - } - } - - return ret; -} - -/** - * Selects this entity. - */ -bool EntityContainer::setSelected(bool select) -{ - // This entity's select: - if (Entity::setSelected(select)) - { - // All sub-entity's select: - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - if (e->isVisible()) - { - e->setSelected(select); - } - } - - return true; - } - else - { - return false; - } -} - -/** - * Toggles select on this entity. - */ -bool EntityContainer::toggleSelected() -{ - // Toggle this entity's select: - if (Entity::toggleSelected()) - { - - // Toggle all sub-entity's select: - /*for (Entity* e=firstEntity(RS2::ResolveNone); - e!=NULL; - e=nextEntity(RS2::ResolveNone)) { - e->toggleSelected(); - }*/ - return true; - } - else - { - return false; - } -} - -/** - * Selects all entities within the given area. - * - * @param select True to select, False to deselect the entities. - */ -void EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross) -{ - bool included; - - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - included = false; - - if (e->isVisible()) - { - if (e->isInWindow(v1, v2)) - { - //e->setSelected(select); - included = true; - } - else if (cross == true) - { - Line l[] = - { - Line(NULL, LineData(v1, Vector(v2.x, v1.y))), - Line(NULL, LineData(Vector(v2.x, v1.y), v2)), - Line(NULL, LineData(v2, Vector(v1.x, v2.y))), - Line(NULL, LineData(Vector(v1.x, v2.y), v1)) - }; - VectorSolutions sol; - - if (e->isContainer()) - { - EntityContainer * ec = (EntityContainer *)e; - - for(Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false; - se=ec->nextEntity(RS2::ResolveAll)) - { - for(int i=0; i<4; ++i) - { - sol = Information::getIntersection(se, &l[i], true); - - if (sol.hasValid()) - { - included = true; - break; - } - } - } - } - else - { - for(int i=0; i<4; ++i) - { - sol = Information::getIntersection(e, &l[i], true); - - if (sol.hasValid()) - { - included = true; - break; - } - } - } - } - } - - if (included) - { - e->setSelected(select); - } - } -} - -/** - * Adds a entity to this container and updates the borders of this - * entity-container if autoUpdateBorders is true. - */ -void EntityContainer::addEntity(Entity * entity) -{ - /* - if (isDocument()) { - LayerList* lst = getDocument()->getLayerList(); - if (lst!=NULL) { - Layer* l = lst->getActive(); - if (l!=NULL && l->isLocked()) { - return; - } - } - } - */ -//printf("EntityContainer::addEntity(): entity=%08X\n", entity); - - if (!entity) - return; - - if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch) - entities.prepend(entity); - else - entities.append(entity); - - if (autoUpdateBorders) - adjustBorders(entity); -//printf(" # of entities=%d\n", entities.size()); -} - -/** - * Inserts a entity to this container at the given position and updates - * the borders of this entity-container if autoUpdateBorders is true. - */ -void EntityContainer::insertEntity(int index, Entity * entity) -{ - if (entity == NULL) - return; - - entities.insert(index, entity); - - if (autoUpdateBorders) - adjustBorders(entity); -} - -/** - * Replaces the entity at the given index with the given entity - * and updates the borders of this entity-container if autoUpdateBorders is true. - */ -void EntityContainer::replaceEntity(int index, Entity * entity) -{ - if (entity == NULL) - return; - - entities.replace(index, entity); - - if (autoUpdateBorders) - adjustBorders(entity); -} - -/** - * Removes an entity from this container and updates the borders of - * this entity-container if autoUpdateBorders is true. - */ -bool EntityContainer::removeEntity(Entity * entity) -{ -// bool ret = entities.remove(entity); - bool ret = (bool)entities.removeAll(entity); - - if (autoUpdateBorders) - calculateBorders(); - - return ret; -} - -/** - * Erases all entities in this container and resets the borders.. - */ -void EntityContainer::clear() -{ - entities.clear(); - resetBorders(); -} - -/** - * Counts all entities (branches of the tree). - */ -unsigned long int EntityContainer::count() -{ - return entities.count(); -} - -/** - * Counts all entities (leaves of the tree). - */ -unsigned long int EntityContainer::countDeep() -{ - unsigned long int c = 0; - - for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone)) - { - c += t->countDeep(); - } - - return c; -} - -/** - * Counts the selected entities in this container. - */ -unsigned long int EntityContainer::countSelected() -{ - unsigned long int c = 0; - - for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone)) - { - if (t->isSelected()) - { - c++; - } - } - - return c; -} - -/** - * Enables / disables automatic update of borders on entity removals - * and additions. By default this is turned on. - */ -/*virtual*/ void EntityContainer::setAutoUpdateBorders(bool enable) -{ - autoUpdateBorders = enable; -} - -/** - * Adjusts the borders of this graphic (max/min values) - */ -void EntityContainer::adjustBorders(Entity * entity) -{ - //DEBUG->print("EntityContainer::adjustBorders"); - //resetBorders(); - - if (entity == NULL) - return; - - // make sure a container is not empty (otherwise the border - // would get extended to 0/0): - if (!entity->isContainer() || entity->count() > 0) - { - minV = Vector::minimum(entity->getMin(), minV); - maxV = Vector::maximum(entity->getMax(), maxV); - } - - // Notify parents. The border for the parent might - // also change TODO: Check for efficiency - //if(parent!=NULL) { - //parent->adjustBorders(this); - //} -} - -/** - * Recalculates the borders of this entity container. - */ -void EntityContainer::calculateBorders() -{ - DEBUG->print("EntityContainer::calculateBorders"); - - resetBorders(); - - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - Layer * layer = e->getLayer(); - - DEBUG->print("EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible()); - - if (e->isVisible() && (layer == NULL || !layer->isFrozen())) - { - e->calculateBorders(); - adjustBorders(e); - } - } - - DEBUG->print("EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y); - - // needed for correcting corrupt data (PLANS.dxf) - if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE - || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE) - { - minV.x = 0.0; - maxV.x = 0.0; - } - - if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE - || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE) - { - minV.y = 0.0; - maxV.y = 0.0; - } - - DEBUG->print("EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y); - - //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y); - - //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y); - //Entity::calculateBorders(); -} - -/** - * Recalculates the borders of this entity container including - * invisible entities. - */ -void EntityContainer::forcedCalculateBorders() -{ - //DEBUG->print("EntityContainer::calculateBorders"); - - resetBorders(); - - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - //Layer* layer = e->getLayer(); - - if (e->isContainer()) - { - ((EntityContainer *)e)->forcedCalculateBorders(); - } - else - { - e->calculateBorders(); - } - - adjustBorders(e); - } - - // needed for correcting corrupt data (PLANS.dxf) - if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE - || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE) - { - minV.x = 0.0; - maxV.x = 0.0; - } - - if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE - || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE) - { - minV.y = 0.0; - maxV.y = 0.0; - } - - //DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y); - - //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y); - //Entity::calculateBorders(); -} - -/** - * Updates all Dimension entities in this container and - * reposition their labels. - */ -void EntityContainer::updateDimensions() -{ - DEBUG->print("EntityContainer::updateDimensions()"); - - //for (Entity* e=firstEntity(RS2::ResolveNone); - // e!=NULL; - // e=nextEntity(RS2::ResolveNone)) { - -#if 0 -// Q3PtrListIterator it = createIterator(); - QListIterator it = createIterator(); -// return QListIterator(entities); - - Entity * e; - - while ((e = it.current()) != NULL) - { - ++it; - - if (Information::isDimension(e->rtti())) - { - // update and reposition label: - ((Dimension *)e)->update(true); - } - else if (e->isContainer()) - { - ((EntityContainer *)e)->updateDimensions(); - } - } -#else - for(int i=0; irtti())) - // update and reposition label: - ((Dimension *)e)->update(true); - else if (e->isContainer()) - ((EntityContainer *)e)->updateDimensions(); - } -#endif - - DEBUG->print("EntityContainer::updateDimensions() OK"); -} - -/** - * Updates all Insert entities in this container. - */ -void EntityContainer::updateInserts() -{ - DEBUG->print("EntityContainer::updateInserts()"); - - //for (Entity* e=firstEntity(RS2::ResolveNone); - // e!=NULL; - // e=nextEntity(RS2::ResolveNone)) { -#if 0 - Q3PtrListIterator it = createIterator(); - Entity * e; - - while ((e = it.current()) != NULL) - { - ++it; - //// Only update our own inserts and not inserts of inserts - if (e->rtti() == RS2::EntityInsert /*&& e->getParent()==this*/) - { - ((Insert *)e)->update(); - } - else if (e->isContainer() && e->rtti() != RS2::EntityHatch) - { - ((EntityContainer *)e)->updateInserts(); - } - } -#else - for(int i=0; irtti() == RS2::EntityInsert /*&& e->getParent()==this*/) - ((Insert *)e)->update(); - else if (e->isContainer() && e->rtti() != RS2::EntityHatch) - ((EntityContainer *)e)->updateInserts(); - } -#endif - - DEBUG->print("EntityContainer::updateInserts() OK"); -} - -/** - * Renames all inserts with name 'oldName' to 'newName'. This is - * called after a block was rename to update the inserts. - */ -void EntityContainer::renameInserts(const QString& oldName, const QString& newName) -{ - DEBUG->print("EntityContainer::renameInserts()"); - - //for (Entity* e=firstEntity(RS2::ResolveNone); - // e!=NULL; - // e=nextEntity(RS2::ResolveNone)) { - -#if 0 - Q3PtrListIterator it = createIterator(); - Entity* e; - while ( (e = it.current()) != NULL ) { - ++it; - - if (e->rtti()==RS2::EntityInsert) { - Insert* i = ((Insert*)e); - if (i->getName()==oldName) { - i->setName(newName); - } - } else if (e->isContainer()) { - ((EntityContainer*)e)->renameInserts(oldName, newName); - } - } -#else - for(int i=0; irtti() == RS2::EntityInsert) - { - Insert * i = ((Insert *)e); - - if (i->getName() == oldName) - i->setName(newName); - } - else if (e->isContainer()) - ((EntityContainer *)e)->renameInserts(oldName, newName); - } -#endif - - DEBUG->print("EntityContainer::renameInserts() OK"); - -} - -/** - * Updates all Spline entities in this container. - */ -void EntityContainer::updateSplines() -{ - DEBUG->print("EntityContainer::updateSplines()"); - - //for (Entity* e=firstEntity(RS2::ResolveNone); - // e!=NULL; - // e=nextEntity(RS2::ResolveNone)) { -#if 0 - Q3PtrListIterator it = createIterator(); - Entity* e; - while ( (e = it.current()) != NULL ) { - ++it; - //// Only update our own inserts and not inserts of inserts - if (e->rtti()==RS2::EntitySpline /*&& e->getParent()==this*/) { - ((Spline*)e)->update(); - } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) { - ((EntityContainer*)e)->updateSplines(); - } - } -#else - for(int i=0; irtti() == RS2::EntitySpline /*&& e->getParent()==this*/) - ((Spline *)e)->update(); - else if (e->isContainer() && e->rtti() != RS2::EntityHatch) - ((EntityContainer *)e)->updateSplines(); - } -#endif - - DEBUG->print("EntityContainer::updateSplines() OK"); -} - -/** - * Updates the sub entities of this container. - */ -void EntityContainer::update() -{ - //for (Entity* e=firstEntity(RS2::ResolveNone); - // e!=NULL; - // e=nextEntity(RS2::ResolveNone)) { -#if 0 - Q3PtrListIterator it = createIterator(); - Entity* e; - while ( (e = it.current()) != NULL ) { - ++it; - e->update(); - } -#else - for(int i=0; iupdate(); - entities[i]->update(); - } -#endif -} - -/** - * Returns the first entity or NULL if this graphic is empty. - * @param level - */ -Entity * EntityContainer::firstEntity(RS2::ResolveLevel level) -{ - switch (level) - { - case RS2::ResolveNone: -// return entities.first(); -// entityIterator.toFront(); - entityIterator = entities; - return (entityIterator.hasNext() ? entityIterator.next() : NULL); - break; - - case RS2::ResolveAllButInserts: - { - subContainer = NULL; -// Entity * e = entities.first(); -// entityIterator.toFront(); - entityIterator = entities; - Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - - if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->firstEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = nextEntity(level); - } - } - - return e; - } - break; - - case RS2::ResolveAll: - { - subContainer = NULL; -// Entity * e = entities.first(); -// entityIterator.toFront(); - entityIterator = entities; - Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - - if (e != NULL && e->isContainer()) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->firstEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = nextEntity(level); - } - } - - return e; - } - break; - } - - return NULL; -} - -/** - * Returns the last entity or \p NULL if this graphic is empty. - * - * @param level \li \p 0 Groups are not resolved - * \li \p 1 (default) only Groups are resolved - * \li \p 2 all Entity Containers are resolved - */ -Entity * EntityContainer::lastEntity(RS2::ResolveLevel level) -{ - switch (level) - { - case RS2::ResolveNone: -// return entities.last(); - entityIterator = entities; - entityIterator.toBack(); - return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - break; - - case RS2::ResolveAllButInserts: - { -// Entity * e = entities.last(); - entityIterator = entities; - entityIterator.toBack(); - Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - subContainer = NULL; - - if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->lastEntity(level); - } - - return e; - } - break; - - case RS2::ResolveAll: - { -// Entity * e = entities.last(); - entityIterator = entities; - entityIterator.toBack(); - Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - subContainer = NULL; - - if (e != NULL && e->isContainer()) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->lastEntity(level); - } - - return e; - } - break; - } - - return NULL; -} - -/** - * Returns the next entity or container or \p NULL if the last entity - * returned by \p next() was the last entity in the container. - */ -Entity * EntityContainer::nextEntity(RS2::ResolveLevel level) -{ - switch (level) - { - case RS2::ResolveNone: -// return entities.next(); - return (entityIterator.hasNext() ? entityIterator.next() : NULL); - break; - - case RS2::ResolveAllButInserts: - { - Entity * e = NULL; - - if (subContainer != NULL) - { - e = subContainer->nextEntity(level); - - if (e != NULL) - { - return e; - } - else - { -// e = entities.next(); - e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - } - } - else - { -// e = entities.next(); - e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - } - - if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->firstEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = nextEntity(level); - } - } - - return e; - } - break; - - case RS2::ResolveAll: - { - Entity * e = NULL; - - if (subContainer != NULL) - { - e = subContainer->nextEntity(level); - - if (e != NULL) - return e; - else -// e = entities.next(); - e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - } - else - { -// e = entities.next(); - e = (entityIterator.hasNext() ? entityIterator.next() : NULL); - } - - if (e != NULL && e->isContainer()) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->firstEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = nextEntity(level); - } - } - - return e; - } - break; - } - return NULL; -} - -/** - * Returns the prev entity or container or \p NULL if the last entity - * returned by \p prev() was the first entity in the container. - */ -Entity * EntityContainer::prevEntity(RS2::ResolveLevel level) -{ - Entity * e = NULL; - - switch (level) - { - case RS2::ResolveNone: -// return entities.prev(); - return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - break; - - case RS2::ResolveAllButInserts: - e = NULL; - - if (subContainer != NULL) - { - e = subContainer->prevEntity(level); - - if (e != NULL) - return e; - else -// e = entities.prev(); - e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - } - else - { -// e = entities.prev(); - e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - } - - if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->lastEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = prevEntity(level); - } - } - - return e; - - case RS2::ResolveAll: - e = NULL; - - if (subContainer != NULL) - { - e = subContainer->prevEntity(level); - - if (e != NULL) - return e; - else -// e = entities.prev(); - e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - } - else - { -// e = entities.prev(); - e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL); - } - - if (e != NULL && e->isContainer()) - { - subContainer = (EntityContainer *)e; - e = ((EntityContainer *)e)->lastEntity(level); - - // emtpy container: - if (e == NULL) - { - subContainer = NULL; - e = prevEntity(level); - } - } - - return e; - } - - return NULL; -} - -/** - * @return Entity at the given index or NULL if the index is out of range. - */ -Entity * EntityContainer::entityAt(uint index) -{ - return entities.at(index); -} - -/** - * @return Current index. - */ -int EntityContainer::entityAt() -{ -#warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)" -// return entities.at(); - return 0; -} - -/** - * Finds the given entity and makes it the current entity if found. - */ -int EntityContainer::findEntity(Entity * entity) -{ -// return entities.find(entity); - - entityIterator.toFront(); - entityIterator.findNext(entity); - - return entities.indexOf(entity); -} - -/** - * @return The current entity. - */ -Entity * EntityContainer::currentEntity() -{ -// return entities.current(); - -// We really need to refactor this crap, this is the way it is now to support -// the old broken way of doing things - return entityIterator.peekNext(); -} - -#if 0 -#warning "!!! Not needed anymore !!!" -/** - * Returns the copy to a new iterator for traversing the entities. - */ -//Q3PtrListIterator EntityContainer::createIterator() -QListIterator EntityContainer::createIterator() -{ -// return Q3PtrListIterator(entities); - return QListIterator(entities); -} -#endif - -/*virtual*/ bool EntityContainer::isEmpty() -{ - return (count() == 0); -} - -/** - * @return The point which is closest to 'coord' - * (one of the vertexes) - */ -Vector EntityContainer::getNearestEndpoint(const Vector & coord, double * dist) -{ - double minDist = RS_MAXDOUBLE; // minimum measured distance - double curDist; // currently measured distance - Vector closestPoint(false); // closest found endpoint - Vector point; // endpoint found - - //Q3PtrListIterator it = createIterator(); - //Entity* en; - //while ( (en = it.current()) != NULL ) { - // ++it; - for (Entity* en = firstEntity(); - en != NULL; - en = nextEntity()) { - - if (en->isVisible()) { - point = en->getNearestEndpoint(coord, &curDist); - if (point.valid && curDistisVisible()) - point = e->getNearestPointOnEntity(coord, onEntity, dist, entity); - - return point; -} - -Vector EntityContainer::getNearestCenter(const Vector & coord, double * dist) -{ - Vector point(false); - Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone); - - if (closestEntity) - point = closestEntity->getNearestCenter(coord, dist); - - return point; -} - -Vector EntityContainer::getNearestMiddle(const Vector & coord, double * dist) -{ - Vector point(false); - Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone); - - if (closestEntity) - point = closestEntity->getNearestMiddle(coord, dist); - - return point; -} - -Vector EntityContainer::getNearestDist(double distance, const Vector & coord, - double * dist) -{ - Vector point(false); - Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone); - - if (closestEntity) - point = closestEntity->getNearestDist(distance, coord, dist); - - return point; -} - -/** - * @return The intersection which is closest to 'coord' - */ -Vector EntityContainer::getNearestIntersection(const Vector & coord, - double * dist) -{ - double minDist = RS_MAXDOUBLE; // minimum measured distance - double curDist; // currently measured distance - Vector closestPoint(false); // closest found endpoint - Vector point; // endpoint found - VectorSolutions sol; - Entity * closestEntity; - - closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll); - - if (closestEntity) - { - for(Entity * en=firstEntity(RS2::ResolveAll); en!=NULL; - en = nextEntity(RS2::ResolveAll)) - { - if (en->isVisible() && en!=closestEntity) - { - sol = Information::getIntersection(closestEntity, en, true); - - for(int i=0; i<4; i++) - { - point = sol.get(i); - - if (point.valid) - { - curDist = coord.distanceTo(point); - - if (curDist < minDist) - { - closestPoint = point; - minDist = curDist; - - if (dist) - *dist = curDist; - } - } - } - } - } - } - - return closestPoint; -} - -Vector EntityContainer::getNearestRef(const Vector & coord, double * dist) -{ - double minDist = RS_MAXDOUBLE; // minimum measured distance - double curDist; // currently measured distance - Vector closestPoint(false); // closest found endpoint - Vector point; // endpoint found - - for(Entity * en=firstEntity(); en!=NULL; en=nextEntity()) - { - if (en->isVisible()) - { - point = en->getNearestRef(coord, &curDist); - - if (point.valid && curDist < minDist) - { - closestPoint = point; - minDist = curDist; - - if (dist) - *dist = curDist; - } - } - } - - return closestPoint; -} - -Vector EntityContainer::getNearestSelectedRef(const Vector & coord, - double * dist) -{ - double minDist = RS_MAXDOUBLE; // minimum measured distance - double curDist; // currently measured distance - Vector closestPoint(false); // closest found endpoint - Vector point; // endpoint found - - for(Entity * en=firstEntity(); en!=NULL; en=nextEntity()) - { - if (en->isVisible() && en->isSelected() && !en->isParentSelected()) - { - point = en->getNearestSelectedRef(coord, &curDist); - - if (point.valid && curDist < minDist) - { - closestPoint = point; - minDist = curDist; - - if (dist) - *dist = curDist; - } - } - } - - return closestPoint; -} - -double EntityContainer::getDistanceToPoint(const Vector & coord, - Entity ** entity, RS2::ResolveLevel level, double solidDist) -{ - DEBUG->print("EntityContainer::getDistanceToPoint"); - - double minDist = RS_MAXDOUBLE; // minimum measured distance - double curDist; // currently measured distance - Entity * closestEntity = NULL; // closest entity found - Entity * subEntity = NULL; - - //int k=0; - for(Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level)) - { - if (e->isVisible()) - { - DEBUG->print("entity: getDistanceToPoint"); - DEBUG->print("entity: %d", e->rtti()); - curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist); - DEBUG->print("entity: getDistanceToPoint: OK"); - - if (curDistprint("EntityContainer::getDistanceToPoint: OK"); - return minDist; -} - -Entity * EntityContainer::getNearestEntity(const Vector & coord, - double * dist, RS2::ResolveLevel level) -{ - DEBUG->print("EntityContainer::getNearestEntity"); - Entity * e = NULL; - - // distance for points inside solids: - double solidDist = RS_MAXDOUBLE; - - if (dist) - solidDist = *dist; - - double d = getDistanceToPoint(coord, &e, level, solidDist); - - if (e && e->isVisible() == false) - e = NULL; - - // if d is negative, use the default distance (used for points inside solids) - if (dist) - *dist = d; - - DEBUG->print("EntityContainer::getNearestEntity: OK"); - return e; -} - -/** - * Rearranges the atomic entities in this container in a way that connected - * entities are stored in the right order and direction. - * Non-recoursive. Only affects atomic entities in this container. - * - * @retval true all contours were closed - * @retval false at least one contour is not closed - */ -bool EntityContainer::optimizeContours() -{ - DEBUG->print("EntityContainer::optimizeContours"); - - Vector current(false); - Vector start(false); - EntityContainer tmp; - - bool changed = false; - bool closed = true; - - for(uint ci=0; ciisEdge() && !e1->isContainer() && !e1->isProcessed()) - { - AtomicEntity * ce = (AtomicEntity *)e1; - - // next contour start: - ce->setProcessed(true); - tmp.addEntity(ce->clone()); - current = ce->getEndpoint(); - start = ce->getStartpoint(); - - // find all connected entities: - bool done; - - do - { - done = true; - for(uint ei=0; eiisEdge() && !e2->isContainer() && - !e2->isProcessed()) - { - AtomicEntity * e = (AtomicEntity *)e2; - - if (e->getStartpoint().distanceTo(current) < 1.0e-4) - { - e->setProcessed(true); - tmp.addEntity(e->clone()); - current = e->getEndpoint(); - done = false; - } - else if (e->getEndpoint().distanceTo(current) < 1.0e-4) - { - e->setProcessed(true); - AtomicEntity * cl = (AtomicEntity *)e->clone(); - cl->reverse(); - tmp.addEntity(cl); - current = cl->getEndpoint(); - changed = true; - done = false; - } - } - } - - if (!done) - changed = true; - } - while (!done); - - if (current.distanceTo(start) > 1.0e-4) - closed = false; - } - } - - // remove all atomic entities: - bool done; - - do - { - done = true; - - for(Entity * en=firstEntity(); en!=NULL; en=nextEntity()) - { - if (!en->isContainer()) - { - removeEntity(en); - done = false; - break; - } - } - } - while (!done); - - // add new sorted entities: - for(Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) - { - en->setProcessed(false); - addEntity(en->clone()); - } - - DEBUG->print("EntityContainer::optimizeContours: OK"); - return closed; -} - -bool EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2) -{ - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - { - if (e->hasEndpointsWithinWindow(v1, v2)) - return true; - } - - return false; -} - -void EntityContainer::move(Vector offset) -{ - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->move(offset); - - if (autoUpdateBorders) - calculateBorders(); -} - -void EntityContainer::rotate(Vector center, double angle) -{ - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->rotate(center, angle); - - if (autoUpdateBorders) - calculateBorders(); -} - -void EntityContainer::scale(Vector center, Vector factor) -{ - if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE) - { - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->scale(center, factor); - } - - if (autoUpdateBorders) - calculateBorders(); -} - -void EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2) -{ - if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6) - { - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->mirror(axisPoint1, axisPoint2); - } -} - -void EntityContainer::stretch(Vector firstCorner, Vector secondCorner, - Vector offset) -{ - if (getMin().isInWindow(firstCorner, secondCorner) && - getMax().isInWindow(firstCorner, secondCorner)) - { - move(offset); - } - else - { - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->stretch(firstCorner, secondCorner, offset); - } - - // some entitiycontainers might need an update (e.g. Leader): - update(); -} - -void EntityContainer::moveRef(const Vector & ref, const Vector & offset) -{ - for(Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->moveRef(ref, offset); - - if (autoUpdateBorders) - calculateBorders(); -} - -void EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset) -{ - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) - e->moveSelectedRef(ref, offset); - - if (autoUpdateBorders) - calculateBorders(); -} - -void EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/) -{ - if (!painter || !view) - return; - - for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) -#if 0 -{ -if (e->rtti() == RS2::EntityText) -{ - std::cout << "About to draw TEXT entity... " - << "TEXT=\"" << ((Text *)e)->getText().toAscii().data() << "\"" << std::endl; -} -//OK, we have text, but no insert entities at least none that are drawn... -//Ah! But with a standard text entity, it DOES have them! -else if (e->rtti() == RS2::EntityInsert) -{ - std::cout << "About to draw INSERT entity... " - << "INSERT=\"" << ((Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl; -} -#endif - view->drawEntity(e); -#if 0 -} -#endif -} - -/** - * Dumps the entities to stdout. - */ -std::ostream & operator<<(std::ostream & os, EntityContainer & ec) -{ - static int indent = 0; - char * tab = new char[indent * 2 + 1]; - - for(int i=0; igetName().toLatin1().data() << "\n"; - } - else - { - os << tab << "Layer[" << id << "]: \n"; - } - //os << ec.layerList << "\n"; - - os << tab << " Flags[" << id << "]: " - << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : ""); - os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : ""); - os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : ""); - os << "\n"; - - os << tab << "Entities[" << id << "]: \n"; - -QString s; -os << "(# of entities in this = " << ec.entities.size() << ")\n"; -for(int i=0; irtti()); - os << s.toAscii().data(); -} -s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity()); -os << s.toAscii().data(); - - for(Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity()) - { - switch (t->rtti()) - { - case RS2::EntityInsert: - os << tab << *((Insert *)t); - os << tab << *((Entity *)t); - os << tab << *((EntityContainer *)t); - break; - default: - if (t->isContainer()) - os << tab << *((EntityContainer *)t); - else - os << tab << *t; - - break; - } - } - - os << tab << "\n\n"; - indent--; - - delete[] tab; - return os; -}