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. :-)
26 #include "graphicview.h"
36 * Default constructor.
37 * @param parent The parent entity of this entity.
38 * E.g. a line might have a graphic entity or
39 * a polyline entity as parent.
41 Entity::Entity(EntityContainer * parent)
43 this->parent = parent;
50 /*Entity::Entity(const Entity& e) : Flags(e.getFlags()) {
51 cout << "copy constructor called\n";
55 //setFlag(e.getFlags());
68 /*virtual*/ void Entity::reparent(EntityContainer * parent)
70 this->parent = parent;
74 * Initialisation. Called from all constructors.
80 setFlag(RS2::FlagVisible);
90 * Gives this entity a new unique id.
94 static unsigned long int idCounter = 0;
99 * Resets the borders of this element.
101 void Entity::resetBorders()
103 // TODO: Check that. windoze XP crashes with MAXDOUBLE
104 double maxd = RS_MAXDOUBLE;
105 double mind = RS_MINDOUBLE;
107 minV.set(maxd, maxd, maxd);
108 maxV.set(mind, mind, mind);
112 * Must be overwritten to return the rtti of this entity
113 * (e.g. RS2::EntityArc).
115 /*virtual*/ RS2::EntityType Entity::rtti() const
117 return RS2::EntityUnknown;
121 * Identify all entities as undoable entities.
122 * @return RS2::UndoableEntity
124 /*virtual*/ RS2::UndoableType Entity::undoRtti()
126 return RS2::UndoableEntity;
130 * @return Unique Id of this entity.
132 unsigned long int Entity::getId() const
138 * Must be overwritten to return true if an entity type
139 * is a potential edge entity of a contour. By default
140 * this returns false.
142 /*virtual*/ bool Entity::isEdge() const
148 * @return true for all document entities (e.g. Graphics or Blocks).
151 /*virtual*/ bool Entity::isDocument() const
157 * Selects or deselects this entity.
159 * @param select True to select, false to deselect.
161 bool Entity::setSelected(bool select)
164 if (select && isLocked())
168 setFlag(RS2::FlagSelected);
170 delFlag(RS2::FlagSelected);
176 * Toggles select on this entity.
178 bool Entity::toggleSelected()
180 return setSelected(!isSelected());
181 //toggleFlag(RS2::FlagSelected);
185 * @return True if the entity is selected. Note that an entity might
186 * not be selected but one of its parents is selected. In that case
187 * this function returns false.
189 bool Entity::isSelected() const
191 return getFlag(RS2::FlagSelected);
195 * @return true if a parent entity of this entity is selected.
197 bool Entity::isParentSelected()
205 if (p && p->isSelected() == true)
214 * Sets or resets the processed flag of this entity.
216 * @param on True to set, false to reset.
218 void Entity::setProcessed(bool on)
221 setFlag(RS2::FlagProcessed);
223 delFlag(RS2::FlagProcessed);
227 * @return True if the processed flag is set.
229 bool Entity::isProcessed() const
231 return getFlag(RS2::FlagProcessed);
235 * Called when the undo state changed.
237 * @param undone true: entity has become invisible.
238 * false: entity has become visible.
240 void Entity::undoStateChanged(bool /*undone*/)
247 * @return true if this entity or any parent entities are undone.
249 bool Entity::isUndone() const
252 return Undoable::isUndone();
254 return Undoable::isUndone() || parent->isUndone();
258 * @return True if the entity is in the given range.
260 bool Entity::isInWindow(Vector v1, Vector v2)
262 double right, left, top, bottom;
264 right = std::max(v1.x, v2.x);
265 left = std::min(v1.x, v2.x);
266 top = std::max(v1.y, v2.y);
267 bottom = std::min(v1.y, v2.y);
269 return (getMin().x >= left && getMax().x <= right
270 && getMin().y >= bottom && getMax().y <= top);
274 * @param tolerance Tolerance.
276 * @retval true if the given point is on this entity.
277 * @retval false otherwise
279 bool Entity::isPointOnEntity(const Vector & coord, double tolerance)
281 double dist = getDistanceToPoint(coord, NULL, RS2::ResolveNone);
282 return (dist <= tolerance);
285 /*virtual*/ bool Entity::hasEndpointsWithinWindow(Vector /*v1*/, Vector /*v2*/)
291 * Is this entity visible?
293 * @return true Only if the entity and the layer it is on are visible.
294 * The Layer might also be NULL. In that case the layer visiblity
297 /*virtual*/ bool Entity::isVisible()
299 if (!getFlag(RS2::FlagVisible))
305 /*EntityCotnainer* parent = getParent();
306 if (parent!=NULL && parent->isUndone()) {
310 if (getLayer() == NULL)
313 // inserts are usually visible - the entities in them have their own
314 // layers which might be frozen
315 // upd: i'm not sure if that is the best behaviour
316 //if (rtti()==RS2::EntityInsert) {
320 if (layer != NULL /*&& layer->getName()!="ByBlock"*/)
322 if (!layer->isFrozen())
328 if (layer == NULL /*&& getLayer()->getName()!="ByBlock"*/)
330 if (getLayer() == NULL)
334 if (!getLayer()->isFrozen())
341 if (getBlockOrInsert() == NULL)
344 if (getBlockOrInsert()->rtti() == RS2::EntityBlock)
346 if (getLayer(false) == NULL || !getLayer(false)->isFrozen())
353 if (getBlockOrInsert()->getLayer() == NULL)
356 if (!getBlockOrInsert()->getLayer()->isFrozen())
362 /*virtual*/ void Entity::setVisible(bool v)
365 setFlag(RS2::FlagVisible);
367 delFlag(RS2::FlagVisible);
371 * Sets the highlight status of the entity. Highlighted entities
372 * usually indicate a feedback to a user action.
374 void Entity::setHighlighted(bool on)
377 setFlag(RS2::FlagHighlighted);
379 delFlag(RS2::FlagHighlighted);
383 * @return true if the entity is highlighted.
385 bool Entity::isHighlighted()
387 return getFlag(RS2::FlagHighlighted);
391 * @return true if the layer this entity is on is locked.
393 bool Entity::isLocked()
395 if (getLayer(true) != NULL && getLayer()->isLocked())
402 * Implementations must return the total length of the entity
403 * or a negative number if the entity has no length (e.g. a text or hatch).
405 /*virtual*/ double Entity::getLength()
411 * @return Parent of this entity or NULL if this is a root entity.
413 EntityContainer * Entity::getParent() const
419 * Reparents this entity.
421 void Entity::setParent(EntityContainer * p)
427 * @return The parent graphic in which this entity is stored
428 * or the parent's parent graphic or NULL if none of the parents
429 * are stored in a graphic.
431 Drawing * Entity::GetDrawing()
433 if (rtti() == RS2::EntityDrawing)
434 return (Drawing *)this;
435 else if (parent == NULL)
438 return parent->GetDrawing();
442 * @return The parent block in which this entity is stored
443 * or the parent's parent block or NULL if none of the parents
444 * are stored in a block.
446 Block * Entity::getBlock()
448 if (rtti() == RS2::EntityBlock)
449 return (Block *)this;
450 else if (parent == NULL)
453 return parent->getBlock();
457 * @return The parent insert in which this entity is stored
458 * or the parent's parent block or NULL if none of the parents
459 * are stored in a block.
461 Insert * Entity::getInsert()
463 if (rtti() == RS2::EntityInsert)
464 return (Insert *)this;
465 else if (parent == NULL)
468 return parent->getInsert();
472 * @return The parent block or insert in which this entity is stored
473 * or the parent's parent block or insert or NULL if none of the parents
474 * are stored in a block or insert.
476 Entity * Entity::getBlockOrInsert()
478 if (rtti() == RS2::EntityBlock || rtti() == RS2::EntityInsert)
480 else if (parent == NULL)
483 return parent->getBlockOrInsert();
487 * @return The parent document in which this entity is stored
488 * or the parent's parent document or NULL if none of the parents
489 * are stored in a document. Note that a document is usually
490 * either a Graphic or a Block.
492 Document * Entity::getDocument()
494 if (isDocument() == true)
495 return (Document *)this;
496 else if (parent == NULL)
499 return parent->getDocument();
503 * Can be implemented by child classes to update the entities
504 * temporary subentities. update() is called if the entity's
505 * paramters or undo state changed.
507 /*virtual*/ void Entity::update()
511 /*virtual*/ void Entity::setUpdateEnabled(bool on)
517 * This method doesn't do any calculations.
518 * @return minimum coordinate of the entity.
519 * @see calculateBorders()
521 Vector Entity::getMin() const
527 * This method doesn't do any calculations.
528 * @return minimum coordinate of the entity.
529 * @see calculateBorders()
531 Vector Entity::getMax() const
537 * This method returns the difference of max and min returned
538 * by the above functions.
539 * @return size of the entity.
540 * @see calculateBorders()
544 Vector Entity::getSize() const
550 * Sets a variable value for the parent graphic object.
552 * @param key Variable name (e.g. "$DIMASZ")
553 * @param val Default value
555 void Entity::addGraphicVariable(const QString & key, double val, int code)
557 Drawing * drawing = GetDrawing();
560 drawing->addVariable(key, val, code);
564 * Sets a variable value for the parent graphic object.
566 * @param key Variable name (e.g. "$DIMASZ")
567 * @param val Default value
569 void Entity::addGraphicVariable(const QString & key, int val, int code)
571 Drawing * drawing = GetDrawing();
574 drawing->addVariable(key, val, code);
578 * Sets a variable value for the parent graphic object.
580 * @param key Variable name (e.g. "$DIMASZ")
581 * @param val Default value
583 void Entity::addGraphicVariable(const QString & key, const QString & val, int code)
585 Drawing * drawing = GetDrawing();
588 drawing->addVariable(key, val, code);
592 * A safe member function to return the given variable.
594 * @param key Variable name (e.g. "$DIMASZ")
595 * @param def Default value
597 * @return value of variable or default value if the given variable
600 double Entity::getGraphicVariableDouble(const QString & key, double def)
602 Drawing * drawing = GetDrawing();
606 ret = drawing->getVariableDouble(key, def);
612 * A safe member function to return the given variable.
614 * @param key Variable name (e.g. "$DIMASZ")
615 * @param def Default value
617 * @return value of variable or default value if the given variable
620 int Entity::getGraphicVariableInt(const QString & key, int def)
622 Drawing * drawing = GetDrawing();
626 ret = drawing->getVariableInt(key, def);
632 * A safe member function to return the given variable.
634 * @param key Variable name (e.g. "$DIMASZ")
635 * @param def Default value
637 * @return value of variable or default value if the given variable
640 QString Entity::getGraphicVariableString(const QString & key, const QString & def)
642 Drawing * drawing = GetDrawing();
646 ret = drawing->getVariableString(key, def);
652 * @return The unit the parent graphic works on or None if there's no
655 RS2::Unit Entity::getGraphicUnit()
657 Drawing * drawing = GetDrawing();
658 RS2::Unit ret = RS2::None;
661 ret = drawing->getUnit();
667 * Must be overwritten to get all reference points of the entity.
669 /*virtual*/ VectorSolutions Entity::getRefPoints()
671 return VectorSolutions();
675 * Must be overwritten to get the point with a given
676 * distance to the start- or endpoint to the given coordinate for this entity.
678 * @param distance Distance to endpoint.
679 * @param startp true = measured from Startpoint, false = measured from Endpoint
681 * @return The point with the given distance to the start- or endpoint.
683 /*virtual*/ Vector Entity::getNearestDist(double /*distance*/, bool /*startp*/)
685 return Vector(false);
689 * Must be overwritten to get the nearest reference point for this entity.
691 * @param coord Coordinate (typically a mouse coordinate)
692 * @param dist Pointer to a value which will contain the measured
693 * distance between 'coord' and the closest point. The passed
694 * pointer can also be NULL in which case the distance will be
697 * @return The closest point with the given distance to the endpoint.
699 /*virtual*/ Vector Entity::getNearestRef(const Vector & coord, double * dist/*= NULL*/)
701 VectorSolutions s = getRefPoints();
703 return s.getClosest(coord, dist);
707 * Gets the nearest reference point of this entity if it is selected.
708 * Containers re-implement this method to return the nearest reference
709 * point of a selected sub entity.
711 * @param coord Coordinate (typically a mouse coordinate)
712 * @param dist Pointer to a value which will contain the measured
713 * distance between 'coord' and the closest point. The passed
714 * pointer can also be NULL in which case the distance will be
717 * @return The closest point with the given distance to the endpoint.
719 /*virtual*/ Vector Entity::getNearestSelectedRef(const Vector & coord, double * dist/*= NULL*/)
722 return getNearestRef(coord, dist);
724 return Vector(false);
728 * Acts like scale(Vector) but with equal factors.
729 * Equal to scale(center, Vector(factor, factor)).
731 /*virtual*/ void Entity::scale(Vector center, double factor)
733 scale(center, Vector(factor, factor));
737 * Implementations must drag the reference point(s) of all
738 * (sub-)entities that are very close to ref by offset.
740 /*virtual*/ void Entity::moveRef(const Vector &/*ref*/, const Vector &/*offset*/)
746 * Implementations must drag the reference point(s) of selected
747 * (sub-)entities that are very close to ref by offset.
749 /*virtual*/ void Entity::moveSelectedRef(const Vector &/*ref*/, const Vector &/*offset*/)
755 * Returns a pointer to the layer this entity is on or NULL.
757 * @para resolve true: if the layer is ByBlock, the layer of the
758 * block this entity is in is returned.
759 * false: the layer of the entity is returned.
761 * @return pointer to the layer this entity is on. If the layer
762 * is set to NULL the layer of the next parent that is not on
763 * layer NULL is returned. If all parents are on layer NULL, NULL
766 Layer * Entity::getLayer(bool resolve) const
770 // we have no layer but a parent that might have one.
771 // return parent's layer instead:
772 if (layer == NULL /*|| layer->getName()=="ByBlock"*/)
775 return parent->getLayer(true);
781 // return our layer. might still be NULL:
786 * Sets the layer of this entity to the layer with the given name
788 void Entity::setLayer(const QString & name)
790 Drawing * drawing = GetDrawing();
791 layer = (drawing ? drawing->findLayer(name) : NULL);
795 * Sets the layer of this entity to the layer given.
797 void Entity::setLayer(Layer * l)
803 * Sets the layer of this entity to the current layer of
804 * the graphic this entity is in. If this entity (and none
805 * of its parents) are in a graphic the layer is set to NULL.
807 void Entity::setLayerToActive()
809 Drawing * drawing = GetDrawing();
810 layer = (drawing ? drawing->getActiveLayer() : NULL);
814 * Gets the pen needed to draw this entity.
815 * The attributes can also come from the layer this entity is on
816 * if the flags are set accordingly.
818 * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen
819 * from the layer or parent..)
820 * false: Don't resolve and return a pen or ByLayer, ByBlock, ...
822 * @return Pen for this entity.
824 Pen Entity::getPen(bool resolve) const
831 Layer * l = getLayer(true);
833 // use parental attributes (e.g. vertex of a polyline, block
834 // entities when they are drawn in block documents):
835 if (!p.isValid() || p.getColor().isByBlock())
838 p = parent->getPen();
840 // use layer attributes:
843 // layer is "ByBlock":
844 /*if (layer->getName()=="ByBlock" && getBlockOrInsert()!=NULL) {
845 p = getBlockOrInsert()->getPen();
848 // use layer's color:
849 if (p.getColor().isByLayer())
850 p.setColor(l->getPen().getColor());
852 // use layer's width:
853 if (p.getWidth() == RS2::WidthByLayer)
854 p.setWidth(l->getPen().getWidth());
856 // use layer's linetype:
857 if (p.getLineType() == RS2::LineByLayer)
858 p.setLineType(l->getPen().getLineType());
867 * Sets the explicit pen for this entity or a pen with special
868 * attributes such as BY_LAYER, ..
870 void Entity::setPen(const Pen & pen)
876 * Sets the pen of this entity to the current pen of
877 * the graphic this entity is in. If this entity (and none
878 * of its parents) are in a graphic the pen is not changed.
880 void Entity::setPenToActive()
882 Document * doc = getDocument();
885 pen = doc->getActivePen();
888 //DEBUG->print(Debug::D_WARNING, "Entity::setPenToActive(): "
889 // "No document / active pen linked to this entity.");
897 * Implementations must stretch the given range of the entity
898 * by the given offset. This default implementation moves the
899 * whole entity if it is completely inside the given range.
901 void Entity::stretch(Vector firstCorner, Vector secondCorner, Vector offset)
903 //e->calculateBorders();
904 if (getMin().isInWindow(firstCorner, secondCorner)
905 && getMax().isInWindow(firstCorner, secondCorner))
910 * @return Factor for scaling the line styles considering the current
911 * paper scaling and the fact that styles are stored in Millimeter.
913 double Entity::getStyleFactor(GraphicView * view)
915 double styleFactor = 1.0;
919 if (view->isPrinting() == false && view->isDraftMode())
920 styleFactor = 1.0 / view->getFactor().x;
923 //styleFactor = getStyleFactor();
924 // the factor caused by the unit:
925 RS2::Unit unit = RS2::None;
926 Drawing * d = GetDrawing();
931 //double scale = d->getPaperScale();
932 styleFactor = Units::convert(1.0, RS2::Millimeter, unit);
936 // the factor caused by the line width:
937 if (((int)getPen(true).getWidth()) > 0)
938 styleFactor *= ((double)getPen(true).getWidth() / 100.0);
939 else if (((int)getPen(true).getWidth()) == 0)
943 if (view->isPrinting() || view->isPrintPreview() || view->isDraftMode() == false)
945 Drawing * drawing = GetDrawing();
947 if (drawing && drawing->getPaperScale() > 1.0e-6)
948 styleFactor /= drawing->getPaperScale();
952 //DEBUG->print("stylefactor: %f", styleFactor);
953 //DEBUG->print("viewfactor: %f", view->getFactor().x);
955 if (styleFactor * view->getFactor().x < 0.2)
962 * @return User defined variable connected to this entity.
964 QString * Entity::getUserDefVar(QString key)
966 // return (this->varList.find(key));
967 return (this->varList.value(key));
971 * Add a user defined variable to this entity.
973 void Entity::setUserDefVar(QString key, QString val)
975 varList.insert(key, new QString(val));
979 * Deletes the given user defined variable.
981 void Entity::delUserDefVar(QString key)
987 * @return A list of all keys connected to this entity.
989 QStringList Entity::getAllKeys()
992 // Q3DictIterator<QString> it(varList);
993 QHashIterator<QString, QString *> it(varList);
995 // for(; it.current(); ++it)
996 // keys.append(it.currentKey());
1000 keys.append(it.key());
1007 * Dumps the elements data to stdout.
1009 std::ostream & operator<<(std::ostream & os, Entity & e)
1011 //os << "Warning: Virtual entity!\n";
1014 os << " {Entity id: " << e.id;
1016 if (e.parent != NULL)
1017 os << " | parent id: " << e.parent->getId() << "\n";
1019 os << " | no parent\n";
1021 os << " flags: " << (e.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1022 os << (e.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1023 os << (e.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1026 if (e.layer == NULL)
1027 os << " layer: NULL ";
1029 os << " layer: " << e.layer->getName().toLatin1().data() << " "
1030 << " layer address: " << (int)(e.layer) << " ";
1032 os << e.pen << "\n";
1034 os << "variable list:\n";
1035 // Q3DictIterator<QString> it(e.varList); // See QDictIterator
1036 QHashIterator<QString, QString *> it(e.varList);
1039 for( ; it.current(); ++it )
1041 #warning "Removed output (Qt3 style iterator)... !!! FIX !!!"
1042 // os << it.currentKey() << ": " << *it.current() << ", ";
1045 while (it.hasNext())
1048 os << (it.key()).toAscii().data() << ": " << (*it.value()).toAscii().data() << ", ";
1052 // There should be a better way than this...
1055 case RS2::EntityPoint:
1059 case RS2::EntityLine:
1063 case RS2::EntityPolyline:
1064 os << (Polyline &)e;
1067 case RS2::EntityArc:
1071 case RS2::EntityCircle:
1075 case RS2::EntityEllipse:
1079 case RS2::EntityInsert:
1083 case RS2::EntityText:
1088 os << "Unknown Entity";