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/21/2010 Added this text. :-)
15 // JLH 06/02/2010 Changed all references of this class from RS_Graphic to
16 // Drawing, as that makes it more clear that this is what it
17 // is (a CAD drawing, not a bitmap).
24 #include "mathextra.h"
29 * Default constructor.
31 Drawing::Drawing(EntityContainer * parent): Document(parent), layerList(),
37 settings.beginGroup("Defaults");
38 setUnit(Units::stringToUnit(settings.value("Unit", "None").toString()));
41 RS2::Unit unit = getUnit();
43 if (unit == RS2::Inch)
45 addVariable("$DIMASZ", 0.1, 40);
46 addVariable("$DIMEXE", 0.05, 40);
47 addVariable("$DIMEXO", 0.025, 40);
48 addVariable("$DIMGAP", 0.025, 40);
49 addVariable("$DIMTXT", 0.1, 40);
53 addVariable("$DIMASZ", Units::convert(2.5, RS2::Millimeter, unit), 40);
54 addVariable("$DIMEXE", Units::convert(1.25, RS2::Millimeter, unit), 40);
55 addVariable("$DIMEXO", Units::convert(0.625, RS2::Millimeter, unit), 40);
56 addVariable("$DIMGAP", Units::convert(0.625, RS2::Millimeter, unit), 40);
57 addVariable("$DIMTXT", Units::convert(2.5, RS2::Millimeter, unit), 40);
70 /** @return RS2::EntityGraphic */
71 /*virtual*/ RS2::EntityType Drawing::rtti() const
73 return RS2::EntityGraphic;
77 * Counts the entities on the given layer.
79 unsigned long int Drawing::countLayerEntities(Layer * layer)
85 for(Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
87 if (t->getLayer()!=NULL && t->getLayer()->getName()==layer->getName())
97 /*virtual*/ LayerList * Drawing::getLayerList()
102 /*virtual*/ BlockList * Drawing::getBlockList()
108 * Clears all layers, blocks and entities of this graphic.
109 * A default layer (0) is created.
111 void Drawing::newDoc()
113 DEBUG->print("Drawing::newDoc");
120 addLayer(new Layer("0"));
121 //addLayer(new Layer("ByBlock"));
127 * Saves this graphic with the current filename and settings.
133 DEBUG->print("Drawing::save");
134 DEBUG->print(" file: %s", filename.toLatin1().data());
135 DEBUG->print(" format: %d", (int)formatType);
136 DEBUG->print(" export...");
137 ret = FILEIO->fileExport(*this, filename, formatType);
142 layerList.setModified(false);
143 blockList.setModified(false);
146 DEBUG->print("Drawing::save ok");
152 * Saves this graphic with the given filename and current settings.
154 bool Drawing::saveAs(const QString & filename, RS2::FormatType type)
156 DEBUG->print("Drawing::saveAs");
158 this->filename = filename;
159 this->formatType = type;
165 * Loads the given file into this graphic.
167 bool Drawing::open(const QString & filename, RS2::FormatType type)
169 DEBUG->print("Drawing::open(%s)", filename.toLatin1().data());
171 this->filename = filename;
175 ret = FILEIO->fileImport(*this, filename, type);
177 layerList.setModified(false);
178 blockList.setModified(false);
180 //cout << *((Drawing*)graphic);
181 //calculateBorders();
182 DEBUG->print("Drawing::open(%s): OK", filename.toLatin1().data());
187 // Wrappers for Layer functions:
188 void Drawing::clearLayers()
193 uint Drawing::countLayers() const
195 return layerList.count();
198 Layer * Drawing::layerAt(uint i)
200 return layerList.at(i);
203 void Drawing::activateLayer(const QString & name)
205 layerList.activate(name);
208 void Drawing::activateLayer(Layer * layer)
210 layerList.activate(layer);
213 Layer * Drawing::getActiveLayer()
215 return layerList.getActive();
218 /*virtual*/ void Drawing::addLayer(Layer * layer)
220 layerList.add(layer);
224 * Removes the given layer and undoes all entities on it.
226 /*virtual*/ void Drawing::removeLayer(Layer * layer)
228 if (layer != NULL && layer->getName() != "0")
230 // remove all entities on that layer:
233 for(Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
235 if (e->getLayer() && e->getLayer()->getName() == layer->getName())
237 e->setUndoState(true);
245 // remove all entities in blocks that are on that layer:
246 for(uint bi=0; bi<blockList.count(); bi++)
248 Block * blk = blockList.at(bi);
252 for(Entity * e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone))
254 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
256 e->setUndoState(true);
264 layerList.remove(layer);
268 /*virtual*/ void Drawing::editLayer(Layer * layer, const Layer & source)
270 layerList.edit(layer, source);
273 Layer * Drawing::findLayer(const QString & name)
275 return layerList.find(name);
278 void Drawing::toggleLayer(const QString & name)
280 layerList.toggle(name);
283 void Drawing::toggleLayer(Layer * layer)
285 layerList.toggle(layer);
288 void Drawing::toggleLayerLock(Layer * layer)
290 layerList.toggleLock(layer);
293 void Drawing::freezeAllLayers(bool freeze)
295 layerList.freezeAll(freeze);
299 void Drawing::addLayerListListener(LayerListListener * listener)
301 layerList.addListener(listener);
304 void Drawing::removeLayerListListener(LayerListListener * listener)
306 layerList.removeListener(listener);
310 // Wrapper for block functions:
312 void Drawing::clearBlocks()
317 uint Drawing::countBlocks()
319 return blockList.count();
322 Block * Drawing::blockAt(uint i)
324 return blockList.at(i);
327 void Drawing::activateBlock(const QString & name)
329 blockList.activate(name);
332 void Drawing::activateBlock(Block * block)
334 blockList.activate(block);
337 Block * Drawing::getActiveBlock()
339 return blockList.getActive();
342 /*virtual*/ bool Drawing::addBlock(Block * block, bool notify/*= true*/)
344 return blockList.add(block, notify);
347 /*virtual*/ void Drawing::addBlockNotification()
349 blockList.addNotification();
352 /*virtual*/ void Drawing::removeBlock(Block * block)
354 blockList.remove(block);
357 Block * Drawing::findBlock(const QString & name)
359 return blockList.find(name);
362 QString Drawing::newBlockName()
364 return blockList.newName();
367 void Drawing::toggleBlock(const QString & name)
369 blockList.toggle(name);
372 void Drawing::toggleBlock(Block * block)
374 blockList.toggle(block);
377 void Drawing::freezeAllBlocks(bool freeze)
379 blockList.freezeAll(freeze);
383 void Drawing::addBlockListListener(BlockListListener * listener)
385 blockList.addListener(listener);
388 void Drawing::removeBlockListListener(BlockListListener * listener)
390 blockList.removeListener(listener);
394 // Wrappers for variable functions:
395 void Drawing::clearVariables()
397 variableDict.clear();
400 int Drawing::countVariables()
402 return variableDict.count();
405 void Drawing::addVariable(const QString & key, const Vector & value, int code)
407 variableDict.add(key, value, code);
410 void Drawing::addVariable(const QString & key, const QString & value, int code)
412 variableDict.add(key, value, code);
415 void Drawing::addVariable(const QString & key, int value, int code)
417 variableDict.add(key, value, code);
420 void Drawing::addVariable(const QString & key, double value, int code)
422 variableDict.add(key, value, code);
425 Vector Drawing::getVariableVector(const QString & key, const Vector & def)
427 return variableDict.getVector(key, def);
430 QString Drawing::getVariableString(const QString & key, const QString & def)
432 return variableDict.getString(key, def);
435 int Drawing::getVariableInt(const QString & key, int def)
437 return variableDict.getInt(key, def);
440 double Drawing::getVariableDouble(const QString & key, double def)
442 return variableDict.getDouble(key, def);
445 void Drawing::removeVariable(const QString & key)
447 variableDict.remove(key);
450 //Q3Dict<Variable> & getVariableDict()
451 QMultiHash<QString, Variable *> & Drawing::getVariableDict()
453 return variableDict.getVariableDict();
457 * @return true if the grid is switched on (visible).
459 bool Drawing::isGridOn()
461 int on = getVariableInt("$GRIDMODE", 1);
467 * Enables / disables the grid.
469 void Drawing::setGridOn(bool on)
471 addVariable("$GRIDMODE", (int)on, 70);
475 * Sets the unit of this graphic to 'u'
477 void Drawing::setUnit(RS2::Unit u)
479 setPaperSize(Units::convert(getPaperSize(), getUnit(), u));
480 addVariable("$INSUNITS", (int)u, 70);
485 * Gets the unit of this graphic
487 RS2::Unit Drawing::getUnit()
489 return (RS2::Unit)getVariableInt("$INSUNITS", 0);
494 * @return The linear format type for this document.
495 * This is determined by the variable "$LUNITS".
497 RS2::LinearFormat Drawing::getLinearFormat()
499 int lunits = getVariableInt("$LUNITS", 2);
509 return RS2::Scientific;
513 return RS2::Engineering;
517 return RS2::Architectural;
521 return RS2::Fractional;
529 * @return The linear precision for this document.
530 * This is determined by the variable "$LUPREC".
532 int Drawing::getLinearPrecision()
534 return getVariableInt("$LUPREC", 4);
538 * @return The angle format type for this document.
539 * This is determined by the variable "$AUNITS".
541 RS2::AngleFormat Drawing::getAngleFormat()
543 int aunits = getVariableInt("$AUNITS", 0);
549 return RS2::DegreesDecimal;
553 return RS2::DegreesMinutesSeconds;
557 return RS2::Gradians;
565 return RS2::Surveyors;
569 return RS2::DegreesDecimal;
573 * @return The linear precision for this document.
574 * This is determined by the variable "$LUPREC".
576 int Drawing::getAnglePrecision()
578 return getVariableInt("$AUPREC", 4);
582 * @return The insertion point of the drawing into the paper space.
583 * This is the distance from the lower left paper edge to the zero
584 * point of the drawing. DXF: $PINSBASE.
586 Vector Drawing::getPaperInsertionBase()
588 return getVariableVector("$PINSBASE", Vector(0.0,0.0));
592 * Sets the PINSBASE variable.
594 void Drawing::setPaperInsertionBase(const Vector & p)
596 addVariable("$PINSBASE", p, 10);
600 * @return Paper size in graphic units.
602 Vector Drawing::getPaperSize()
604 Vector def = Units::convert(Vector(210.0, 297.0), RS2::Millimeter, getUnit());
605 Vector v1 = getVariableVector("$PLIMMIN", Vector(0.0, 0.0));
606 Vector v2 = getVariableVector("$PLIMMAX", def);
612 * Sets a new paper size.
614 void Drawing::setPaperSize(const Vector & s)
616 addVariable("$PLIMMIN", Vector(0.0, 0.0), 10);
617 addVariable("$PLIMMAX", s, 10);
621 * @return Paper format.
622 * This is determined by the variables "$PLIMMIN" and "$PLIMMAX".
624 * @param landscape will be set to true for landscape and false for portrait if not NULL.
626 RS2::PaperFormat Drawing::getPaperFormat(bool * landscape)
628 Vector size = Units::convert(getPaperSize(), getUnit(), RS2::Millimeter);
630 if (landscape != NULL)
631 *landscape = (size.x > size.y);
633 return Units::paperSizeToFormat(size);
637 * Sets the paper format to the given format.
639 void Drawing::setPaperFormat(RS2::PaperFormat f, bool landscape)
641 Vector size = Units::paperFormatToSize(f);
650 if (f != RS2::Custom)
651 setPaperSize(Units::convert(size, RS2::Millimeter, getUnit()));
655 * @return Paper space scaling (DXF: $PSVPSCALE).
657 double Drawing::getPaperScale()
661 ret = getVariableDouble("$PSVPSCALE", 1.0);
670 * Sets a new scale factor for the paper space.
672 void Drawing::setPaperScale(double s)
674 addVariable("$PSVPSCALE", s, 40);
678 * Centers drawing on page. Affects DXF variable $PINSBASE.
680 void Drawing::centerToPage()
682 Vector size = getPaperSize();
683 double scale = getPaperScale();
684 Vector pinsbase = (size - getSize() * scale) / 2.0 - getMin() * scale;
685 setPaperInsertionBase(pinsbase);
689 * Fits drawing on page. Affects DXF variable $PINSBASE.
691 void Drawing::fitToPage()
693 double border = Units::convert(25.0, RS2::Millimeter, getUnit());
694 Vector ps = getPaperSize() - Vector(border, border);
695 Vector s = getSize();
696 double fx = RS_MAXDOUBLE;
697 double fy = RS_MAXDOUBLE;
698 //double factor = 1.0;
700 //ps = Units::convert(ps, getUnit(), RS2::Millimeter);
702 if (fabs(s.x) > 1.0e-6)
705 if (fabs(s.y) > 1.0e-6)
708 setPaperScale(std::min(fx, fy));
713 * @retval true The document has been modified since it was last saved.
714 * @retval false The document has not been modified since it was last saved.
716 /*virtual*/ bool Drawing::isModified() const
718 return modified || layerList.isModified() || blockList.isModified();
722 * Sets the documents modified status to 'm'.
724 /*virtual*/ void Drawing::setModified(bool m)
727 layerList.setModified(m);
728 blockList.setModified(m);
732 RS_CamData & Drawing::getCamData()
737 void Drawing::setCamData(const RS_CamData & d)
744 * Dumps the entities to stdout.
746 std::ostream & operator<<(std::ostream & os, Drawing & g)
748 os << "--- Drawing: \n";
749 os << "---" << *g.getLayerList() << "\n";
750 os << "---" << *g.getBlockList() << "\n";
751 os << "---" << (Undo &)g << "\n";
752 os << "---" << (EntityContainer &)g << "\n";