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).
23 #include "rs_fileio.h"
29 * Default constructor.
31 Drawing::Drawing(RS_EntityContainer * parent): RS_Document(parent), layerList(),
37 settings.beginGroup("Defaults");
38 setUnit(RS_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", RS_Units::convert(2.5, RS2::Millimeter, unit), 40);
54 addVariable("$DIMEXE", RS_Units::convert(1.25, RS2::Millimeter, unit), 40);
55 addVariable("$DIMEXO", RS_Units::convert(0.625, RS2::Millimeter, unit), 40);
56 addVariable("$DIMGAP", RS_Units::convert(0.625, RS2::Millimeter, unit), 40);
57 addVariable("$DIMTXT", RS_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(RS_Layer * layer)
85 for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
87 if (t->getLayer()!=NULL && t->getLayer()->getName()==layer->getName())
97 /*virtual*/ RS_LayerList * Drawing::getLayerList()
102 /*virtual*/ RS_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 RS_DEBUG->print("Drawing::newDoc");
120 addLayer(new RS_Layer("0"));
121 //addLayer(new RS_Layer("ByBlock"));
127 * Saves this graphic with the current filename and settings.
133 RS_DEBUG->print("Drawing::save");
134 RS_DEBUG->print(" file: %s", filename.toLatin1().data());
135 RS_DEBUG->print(" format: %d", (int)formatType);
137 RS_DEBUG->print(" export...");
138 ret = RS_FILEIO->fileExport(*this, filename, formatType);
143 layerList.setModified(false);
144 blockList.setModified(false);
147 RS_DEBUG->print("Drawing::save ok");
153 * Saves this graphic with the given filename and current settings.
155 bool Drawing::saveAs(const QString & filename, RS2::FormatType type)
157 RS_DEBUG->print("Drawing::saveAs");
159 this->filename = filename;
160 this->formatType = type;
166 * Loads the given fils into this graphic.
168 bool Drawing::open(const QString &filename, RS2::FormatType type)
170 RS_DEBUG->print("Drawing::open(%s)", filename.toLatin1().data());
174 this->filename = filename;
180 ret = RS_FILEIO->fileImport(*this, filename, type);
183 layerList.setModified(false);
184 blockList.setModified(false);
186 //cout << *((Drawing*)graphic);
187 //calculateBorders();
189 RS_DEBUG->print("Drawing::open(%s): OK", filename.toLatin1().data());
194 // Wrappers for Layer functions:
195 void Drawing::clearLayers()
200 uint Drawing::countLayers() const
202 return layerList.count();
205 RS_Layer * Drawing::layerAt(uint i)
207 return layerList.at(i);
210 void Drawing::activateLayer(const QString & name)
212 layerList.activate(name);
215 void Drawing::activateLayer(RS_Layer * layer)
217 layerList.activate(layer);
220 RS_Layer * Drawing::getActiveLayer()
222 return layerList.getActive();
225 /*virtual*/ void Drawing::addLayer(RS_Layer * layer)
227 layerList.add(layer);
231 * Removes the given layer and undoes all entities on it.
233 /*virtual*/ void Drawing::removeLayer(RS_Layer * layer)
235 if (layer != NULL && layer->getName() != "0")
237 // remove all entities on that layer:
240 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
242 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
244 e->setUndoState(true);
252 // remove all entities in blocks that are on that layer:
253 for(uint bi=0; bi<blockList.count(); bi++)
255 RS_Block * blk = blockList.at(bi);
259 for(RS_Entity * e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone))
261 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
263 e->setUndoState(true);
271 layerList.remove(layer);
275 /*virtual*/ void Drawing::editLayer(RS_Layer * layer, const RS_Layer & source)
277 layerList.edit(layer, source);
280 RS_Layer * Drawing::findLayer(const QString & name)
282 return layerList.find(name);
285 void Drawing::toggleLayer(const QString & name)
287 layerList.toggle(name);
290 void Drawing::toggleLayer(RS_Layer * layer)
292 layerList.toggle(layer);
295 void Drawing::toggleLayerLock(RS_Layer * layer)
297 layerList.toggleLock(layer);
300 void Drawing::freezeAllLayers(bool freeze)
302 layerList.freezeAll(freeze);
306 void Drawing::addLayerListListener(RS_LayerListListener * listener)
308 layerList.addListener(listener);
311 void Drawing::removeLayerListListener(RS_LayerListListener * listener)
313 layerList.removeListener(listener);
317 // Wrapper for block functions:
319 void Drawing::clearBlocks()
324 uint Drawing::countBlocks()
326 return blockList.count();
329 RS_Block * Drawing::blockAt(uint i)
331 return blockList.at(i);
334 void Drawing::activateBlock(const QString & name)
336 blockList.activate(name);
339 void Drawing::activateBlock(RS_Block * block)
341 blockList.activate(block);
344 RS_Block * Drawing::getActiveBlock()
346 return blockList.getActive();
349 /*virtual*/ bool Drawing::addBlock(RS_Block * block, bool notify/*= true*/)
351 return blockList.add(block, notify);
354 /*virtual*/ void Drawing::addBlockNotification()
356 blockList.addNotification();
359 /*virtual*/ void Drawing::removeBlock(RS_Block * block)
361 blockList.remove(block);
364 RS_Block * Drawing::findBlock(const QString & name)
366 return blockList.find(name);
369 QString Drawing::newBlockName()
371 return blockList.newName();
374 void Drawing::toggleBlock(const QString & name)
376 blockList.toggle(name);
379 void Drawing::toggleBlock(RS_Block * block)
381 blockList.toggle(block);
384 void Drawing::freezeAllBlocks(bool freeze)
386 blockList.freezeAll(freeze);
390 void Drawing::addBlockListListener(RS_BlockListListener * listener)
392 blockList.addListener(listener);
395 void Drawing::removeBlockListListener(RS_BlockListListener * listener)
397 blockList.removeListener(listener);
401 // Wrappers for variable functions:
402 void Drawing::clearVariables()
404 variableDict.clear();
407 int Drawing::countVariables()
409 return variableDict.count();
412 void Drawing::addVariable(const QString & key, const Vector & value, int code)
414 variableDict.add(key, value, code);
417 void Drawing::addVariable(const QString & key, const QString & value, int code)
419 variableDict.add(key, value, code);
422 void Drawing::addVariable(const QString & key, int value, int code)
424 variableDict.add(key, value, code);
427 void Drawing::addVariable(const QString & key, double value, int code)
429 variableDict.add(key, value, code);
432 Vector Drawing::getVariableVector(const QString & key, const Vector & def)
434 return variableDict.getVector(key, def);
437 QString Drawing::getVariableString(const QString & key, const QString & def)
439 return variableDict.getString(key, def);
442 int Drawing::getVariableInt(const QString & key, int def)
444 return variableDict.getInt(key, def);
447 double Drawing::getVariableDouble(const QString & key, double def)
449 return variableDict.getDouble(key, def);
452 void Drawing::removeVariable(const QString & key)
454 variableDict.remove(key);
457 //Q3Dict<RS_Variable> & getVariableDict()
458 QMultiHash<QString, RS_Variable *> & Drawing::getVariableDict()
460 return variableDict.getVariableDict();
464 * @return true if the grid is switched on (visible).
466 bool Drawing::isGridOn()
468 int on = getVariableInt("$GRIDMODE", 1);
474 * Enables / disables the grid.
476 void Drawing::setGridOn(bool on)
478 addVariable("$GRIDMODE", (int)on, 70);
482 * Sets the unit of this graphic to 'u'
484 void Drawing::setUnit(RS2::Unit u)
486 setPaperSize(RS_Units::convert(getPaperSize(), getUnit(), u));
487 addVariable("$INSUNITS", (int)u, 70);
492 * Gets the unit of this graphic
494 RS2::Unit Drawing::getUnit()
496 return (RS2::Unit)getVariableInt("$INSUNITS", 0);
501 * @return The linear format type for this document.
502 * This is determined by the variable "$LUNITS".
504 RS2::LinearFormat Drawing::getLinearFormat()
506 int lunits = getVariableInt("$LUNITS", 2);
516 return RS2::Scientific;
520 return RS2::Engineering;
524 return RS2::Architectural;
528 return RS2::Fractional;
536 * @return The linear precision for this document.
537 * This is determined by the variable "$LUPREC".
539 int Drawing::getLinearPrecision()
541 return getVariableInt("$LUPREC", 4);
545 * @return The angle format type for this document.
546 * This is determined by the variable "$AUNITS".
548 RS2::AngleFormat Drawing::getAngleFormat()
550 int aunits = getVariableInt("$AUNITS", 0);
556 return RS2::DegreesDecimal;
560 return RS2::DegreesMinutesSeconds;
564 return RS2::Gradians;
572 return RS2::Surveyors;
576 return RS2::DegreesDecimal;
580 * @return The linear precision for this document.
581 * This is determined by the variable "$LUPREC".
583 int Drawing::getAnglePrecision()
585 return getVariableInt("$AUPREC", 4);
589 * @return The insertion point of the drawing into the paper space.
590 * This is the distance from the lower left paper edge to the zero
591 * point of the drawing. DXF: $PINSBASE.
593 Vector Drawing::getPaperInsertionBase()
595 return getVariableVector("$PINSBASE", Vector(0.0,0.0));
599 * Sets the PINSBASE variable.
601 void Drawing::setPaperInsertionBase(const Vector & p)
603 addVariable("$PINSBASE", p, 10);
607 * @return Paper size in graphic units.
609 Vector Drawing::getPaperSize()
611 Vector def = RS_Units::convert(Vector(210.0, 297.0), RS2::Millimeter, getUnit());
612 Vector v1 = getVariableVector("$PLIMMIN", Vector(0.0, 0.0));
613 Vector v2 = getVariableVector("$PLIMMAX", def);
619 * Sets a new paper size.
621 void Drawing::setPaperSize(const Vector & s)
623 addVariable("$PLIMMIN", Vector(0.0, 0.0), 10);
624 addVariable("$PLIMMAX", s, 10);
628 * @return Paper format.
629 * This is determined by the variables "$PLIMMIN" and "$PLIMMAX".
631 * @param landscape will be set to true for landscape and false for portrait if not NULL.
633 RS2::PaperFormat Drawing::getPaperFormat(bool * landscape)
635 Vector size = RS_Units::convert(getPaperSize(), getUnit(), RS2::Millimeter);
637 if (landscape != NULL)
638 *landscape = (size.x > size.y);
640 return RS_Units::paperSizeToFormat(size);
644 * Sets the paper format to the given format.
646 void Drawing::setPaperFormat(RS2::PaperFormat f, bool landscape)
648 Vector size = RS_Units::paperFormatToSize(f);
657 if (f != RS2::Custom)
658 setPaperSize(RS_Units::convert(size, RS2::Millimeter, getUnit()));
662 * @return Paper space scaling (DXF: $PSVPSCALE).
664 double Drawing::getPaperScale()
668 ret = getVariableDouble("$PSVPSCALE", 1.0);
677 * Sets a new scale factor for the paper space.
679 void Drawing::setPaperScale(double s)
681 addVariable("$PSVPSCALE", s, 40);
685 * Centers drawing on page. Affects DXF variable $PINSBASE.
687 void Drawing::centerToPage()
689 Vector size = getPaperSize();
690 double scale = getPaperScale();
691 Vector pinsbase = (size - getSize() * scale) / 2.0 - getMin() * scale;
692 setPaperInsertionBase(pinsbase);
696 * Fits drawing on page. Affects DXF variable $PINSBASE.
698 void Drawing::fitToPage()
700 double border = RS_Units::convert(25.0, RS2::Millimeter, getUnit());
701 Vector ps = getPaperSize() - Vector(border, border);
702 Vector s = getSize();
703 double fx = RS_MAXDOUBLE;
704 double fy = RS_MAXDOUBLE;
705 //double factor = 1.0;
707 //ps = RS_Units::convert(ps, getUnit(), RS2::Millimeter);
709 if (fabs(s.x) > 1.0e-6)
712 if (fabs(s.y) > 1.0e-6)
715 setPaperScale(std::min(fx, fy));
720 * @retval true The document has been modified since it was last saved.
721 * @retval false The document has not been modified since it was last saved.
723 /*virtual*/ bool Drawing::isModified() const
725 return modified || layerList.isModified() || blockList.isModified();
729 * Sets the documents modified status to 'm'.
731 /*virtual*/ void Drawing::setModified(bool m)
734 layerList.setModified(m);
735 blockList.setModified(m);
739 RS_CamData & Drawing::getCamData()
744 void Drawing::setCamData(const RS_CamData & d)
751 * Dumps the entities to stdout.
753 std::ostream & operator<<(std::ostream & os, Drawing & g)
755 os << "--- Drawing: \n";
756 os << "---" << *g.getLayerList() << "\n";
757 os << "---" << *g.getBlockList() << "\n";
758 os << "---" << (RS_Undo &)g << "\n";
759 os << "---" << (RS_EntityContainer &)g << "\n";