From Paul de Repentinguy, DXF loader plugin. Ported to Linux by Robert Osfield.

This commit is contained in:
Robert Osfield
2005-04-15 20:39:06 +00:00
parent 08f593a54b
commit 47a2b3aa23
23 changed files with 3094 additions and 1 deletions

View File

@@ -0,0 +1,24 @@
TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
aci.cpp\
dxfBlock.cpp\
dxfEntity.cpp\
dxfFile.cpp\
dxfReader.cpp\
dxfSection.cpp\
dxfTable.cpp\
ReaderWriterDXF.cpp\
scene.cpp\
INC += -I$(THISDIR)
LIBS += $(OSG_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = dxf
include $(TOPDIR)/Make/cygwin_plugin_def
PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,61 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <map>
#include <iostream>
#include <utility>
#include <string>
#include <sstream>
#include "dxfFile.h"
using namespace osg;
using namespace osgDB;
using namespace std;
class ReaderWriterdxf : public osgDB::ReaderWriter
{
public:
ReaderWriterdxf() { }
virtual const char* className() { return "Autodesk DXF Reader"; }
virtual bool acceptsExtension(const std::string& extension) const {
return osgDB::equalCaseInsensitive(extension,"dxf");
}
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;
protected:
};
// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterdxf> g_dxfReaderWriterProxy;
// read file and convert to OSG.
osgDB::ReaderWriter::ReadResult
ReaderWriterdxf::readNode(const std::string& filename, const osgDB::ReaderWriter::Options*) const
{
std::string ext = osgDB::getFileExtension(filename);
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
// Open
dxfFile df(filename);
if (df.parseFile()) {
// convert to OSG
osg::Group* osg_top = df.dxf2osg();
return (osg_top);
}
return ReadResult::FILE_NOT_HANDLED;
}

273
src/osgPlugins/dxf/aci.cpp Normal file
View File

@@ -0,0 +1,273 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "aci.h"
double aci::table[256*3] =
{
/* dummy */ 0,0,0,
/* 1 */ 1,0,0,
/* 2 */ 1,1,0,
/* 3 */ 0,1,0,
/* 4 */ 0,1,1,
/* 5 */ 0,0,1,
/* 6 */ 1,0,1,
/* 7 */ 1,1,1,
/* 8 user defined */ 1,1,1,
/* 9 user defined */ 1,1,1,
/* 10 */ 1,0,0,
/* 11 */ 1,0.5,0.5,
/* 12 */ 0.65,0,0,
/* 13 */ 0.65,0.325,0.325,
/* 14 */ 0.5,0,0,
/* 15 */ 0.5,0.25,0.25,
/* 16 */ 0.3,0,0,
/* 17 */ 0.3,0.15,0.15,
/* 18 */ 0.15,0,0,
/* 19 */ 0.15,0.075,0.075,
/* 20 */ 1,0.25,0,
/* 21 */ 1,0.625,0.5,
/* 22 */ 0.65,0.1625,0,
/* 23 */ 0.65,0.4063,0.325,
/* 24 */ 0.5,0.125,0,
/* 25 */ 0.5,0.3125,0.25,
/* 26 */ 0.3,0.075,0,
/* 27 */ 0.3,0.1875,0.15,
/* 28 */ 0.15,0.0375,0,
/* 29 */ 0.15,0.0938,0.075,
/* 30 */ 1,0.5,0,
/* 31 */ 1,0.75,0.5,
/* 32 */ 0.65,0.325,0,
/* 33 */ 0.65,0.4875,0.325,
/* 34 */ 0.5,0.25,0,
/* 35 */ 0.5,0.375,0.25,
/* 36 */ 0.3,0.15,0,
/* 37 */ 0.3,0.225,0.15,
/* 38 */ 0.15,0.075,0,
/* 39 */ 0.15,0.1125,0.075,
/* 40 */ 1,0.75,0,
/* 41 */ 1,0.875,0.5,
/* 42 */ 0.65,0.4875,0,
/* 43 */ 0.65,0.5688,0.325,
/* 44 */ 0.5,0.375,0,
/* 45 */ 0.5,0.4375,0.25,
/* 46 */ 0.3,0.225,0,
/* 47 */ 0.3,0.2625,0.15,
/* 48 */ 0.15,0.1125,0,
/* 49 */ 0.15,0.1313,0.075,
/* 50 */ 1,1,0,
/* 51 */ 1,1,0.5,
/* 52 */ 0.65,0.65,0,
/* 53 */ 0.65,0.65,0.325,
/* 54 */ 0.5,0.5,0,
/* 55 */ 0.5,0.5,0.25,
/* 56 */ 0.3,0.3,0,
/* 57 */ 0.3,0.3,0.15,
/* 58 */ 0.15,0.15,0,
/* 59 */ 0.15,0.15,0.075,
/* 60 */ 0.75,1,0,
/* 61 */ 0.875,1,0.5,
/* 62 */ 0.4875,0.65,0,
/* 63 */ 0.5688,0.65,0.325,
/* 64 */ 0.375,0.5,0,
/* 65 */ 0.4375,0.5,0.25,
/* 66 */ 0.225,0.3,0,
/* 67 */ 0.2625,0.3,0.15,
/* 68 */ 0.1125,0.15,0,
/* 69 */ 0.1313,0.15,0.075,
/* 70 */ 0.5,1,0,
/* 71 */ 0.75,1,0.5,
/* 72 */ 0.325,0.65,0,
/* 73 */ 0.4875,0.65,0.325,
/* 74 */ 0.25,0.5,0,
/* 75 */ 0.375,0.5,0.25,
/* 76 */ 0.15,0.3,0,
/* 77 */ 0.225,0.3,0.15,
/* 78 */ 0.075,0.15,0,
/* 79 */ 0.1125,0.15,0.075,
/* 80 */ 0.25,1,0,
/* 81 */ 0.625,1,0.5,
/* 82 */ 0.1625,0.65,0,
/* 83 */ 0.4063,0.65,0.325,
/* 84 */ 0.125,0.5,0,
/* 85 */ 0.3125,0.5,0.25,
/* 86 */ 0.075,0.3,0,
/* 87 */ 0.1875,0.3,0.15,
/* 88 */ 0.0375,0.15,0,
/* 89 */ 0.0938,0.15,0.075,
/* 90 */ 0,1,0,
/* 91 */ 0.5,1,0.5,
/* 92 */ 0,0.65,0,
/* 93 */ 0.325,0.65,0.325,
/* 94 */ 0,0.5,0,
/* 95 */ 0.25,0.5,0.25,
/* 96 */ 0,0.3,0,
/* 97 */ 0.15,0.3,0.15,
/* 98 */ 0,0.15,0,
/* 99 */ 0.075,0.15,0.075,
/* 100 */ 0,1,0.25,
/* 101 */ 0.5,1,0.625,
/* 102 */ 0,0.65,0.1625,
/* 103 */ 0.325,0.65,0.4063,
/* 104 */ 0,0.5,0.125,
/* 105 */ 0.25,0.5,0.3125,
/* 106 */ 0,0.3,0.075,
/* 107 */ 0.15,0.3,0.1875,
/* 108 */ 0,0.15,0.0375,
/* 109 */ 0.075,0.15,0.0938,
/* 110 */ 0,1,0.5,
/* 111 */ 0.5,1,0.75,
/* 112 */ 0,0.65,0.325,
/* 113 */ 0.325,0.65,0.4875,
/* 114 */ 0,0.5,0.25,
/* 115 */ 0.25,0.5,0.375,
/* 116 */ 0,0.3,0.15,
/* 117 */ 0.15,0.3,0.225,
/* 118 */ 0,0.15,0.075,
/* 119 */ 0.075,0.15,0.1125,
/* 120 */ 0,1,0.75,
/* 121 */ 0.5,1,0.875,
/* 122 */ 0,0.65,0.4875,
/* 123 */ 0.325,0.65,0.5688,
/* 124 */ 0,0.5,0.375,
/* 125 */ 0.25,0.5,0.4375,
/* 126 */ 0,0.3,0.225,
/* 127 */ 0.15,0.3,0.2625,
/* 128 */ 0,0.15,0.1125,
/* 129 */ 0.075,0.15,0.1313,
/* 130 */ 0,1,1,
/* 131 */ 0.5,1,1,
/* 132 */ 0,0.65,0.65,
/* 133 */ 0.325,0.65,0.65,
/* 134 */ 0,0.5,0.5,
/* 135 */ 0.25,0.5,0.5,
/* 136 */ 0,0.3,0.3,
/* 137 */ 0.15,0.3,0.3,
/* 138 */ 0,0.15,0.15,
/* 139 */ 0.075,0.15,0.15,
/* 140 */ 0,0.75,1,
/* 141 */ 0.5,0.875,1,
/* 142 */ 0,0.4875,0.65,
/* 143 */ 0.325,0.5688,0.65,
/* 144 */ 0,0.375,0.5,
/* 145 */ 0.25,0.4375,0.5,
/* 146 */ 0,0.225,0.3,
/* 147 */ 0.15,0.2625,0.3,
/* 148 */ 0,0.1125,0.15,
/* 149 */ 0.075,0.1313,0.15,
/* 150 */ 0,0.5,1,
/* 151 */ 0.5,0.75,1,
/* 152 */ 0,0.325,0.65,
/* 153 */ 0.325,0.4875,0.65,
/* 154 */ 0,0.25,0.5,
/* 155 */ 0.25,0.375,0.5,
/* 156 */ 0,0.15,0.3,
/* 157 */ 0.15,0.225,0.3,
/* 158 */ 0,0.075,0.15,
/* 159 */ 0.075,0.1125,0.15,
/* 160 */ 0,0.25,1,
/* 161 */ 0.5,0.625,1,
/* 162 */ 0,0.1625,0.65,
/* 163 */ 0.325,0.4063,0.65,
/* 164 */ 0,0.125,0.5,
/* 165 */ 0.25,0.3125,0.5,
/* 166 */ 0,0.075,0.3,
/* 167 */ 0.15,0.1875,0.3,
/* 168 */ 0,0.0375,0.15,
/* 169 */ 0.075,0.0938,0.15,
/* 170 */ 0,0,1,
/* 171 */ 0.5,0.5,1,
/* 172 */ 0,0,0.65,
/* 173 */ 0.325,0.325,0.65,
/* 174 */ 0,0,0.5,
/* 175 */ 0.25,0.25,0.5,
/* 176 */ 0,0,0.3,
/* 177 */ 0.15,0.15,0.3,
/* 178 */ 0,0,0.15,
/* 179 */ 0.075,0.075,0.15,
/* 180 */ 0.25,0,1,
/* 181 */ 0.625,0.5,1,
/* 182 */ 0.1625,0,0.65,
/* 183 */ 0.4063,0.325,0.65,
/* 184 */ 0.125,0,0.5,
/* 185 */ 0.3125,0.25,0.5,
/* 186 */ 0.075,0,0.3,
/* 187 */ 0.1875,0.15,0.3,
/* 188 */ 0.0375,0,0.15,
/* 189 */ 0.0938,0.075,0.15,
/* 190 */ 0.5,0,1,
/* 191 */ 0.75,0.5,1,
/* 192 */ 0.325,0,0.65,
/* 193 */ 0.4875,0.325,0.65,
/* 194 */ 0.25,0,0.5,
/* 195 */ 0.375,0.25,0.5,
/* 196 */ 0.15,0,0.3,
/* 197 */ 0.225,0.15,0.3,
/* 198 */ 0.075,0,0.15,
/* 199 */ 0.1125,0.075,0.15,
/* 200 */ 0.75,0,1,
/* 201 */ 0.875,0.5,1,
/* 202 */ 0.4875,0,0.65,
/* 203 */ 0.5688,0.325,0.65,
/* 204 */ 0.375,0,0.5,
/* 205 */ 0.4375,0.25,0.5,
/* 206 */ 0.225,0,0.3,
/* 207 */ 0.2625,0.15,0.3,
/* 208 */ 0.1125,0,0.15,
/* 209 */ 0.1313,0.075,0.15,
/* 210 */ 1,0,1,
/* 211 */ 1,0.5,1,
/* 212 */ 0.65,0,0.65,
/* 213 */ 0.65,0.325,0.65,
/* 214 */ 0.5,0,0.5,
/* 215 */ 0.5,0.25,0.5,
/* 216 */ 0.3,0,0.3,
/* 217 */ 0.3,0.15,0.3,
/* 218 */ 0.15,0,0.15,
/* 219 */ 0.15,0.075,0.15,
/* 220 */ 1,0,0.75,
/* 221 */ 1,0.5,0.875,
/* 222 */ 0.65,0,0.4875,
/* 223 */ 0.65,0.325,0.5688,
/* 224 */ 0.5,0,0.375,
/* 225 */ 0.5,0.25,0.4375,
/* 226 */ 0.3,0,0.225,
/* 227 */ 0.3,0.15,0.2625,
/* 228 */ 0.15,0,0.1125,
/* 229 */ 0.15,0.075,0.1313,
/* 230 */ 1,0,0.5,
/* 231 */ 1,0.5,0.75,
/* 232 */ 0.65,0,0.325,
/* 233 */ 0.65,0.325,0.4875,
/* 234 */ 0.5,0,0.25,
/* 235 */ 0.5,0.25,0.375,
/* 236 */ 0.3,0,0.15,
/* 237 */ 0.3,0.15,0.225,
/* 238 */ 0.15,0,0.075,
/* 239 */ 0.15,0.075,0.1125,
/* 240 */ 1,0,0.25,
/* 241 */ 1,0.5,0.625,
/* 242 */ 0.65,0,0.1625,
/* 243 */ 0.65,0.325,0.4063,
/* 244 */ 0.5,0,0.125,
/* 245 */ 0.5,0.25,0.3125,
/* 246 */ 0.3,0,0.075,
/* 247 */ 0.3,0.15,0.1875,
/* 248 */ 0.15,0,0.0375,
/* 249 */ 0.15,0.075,0.0938,
/* 250 */ 0.33,0.33,0.33,
/* 251 */ 0.464,0.464,0.464,
/* 252 */ 0.598,0.598,0.598,
/* 253 */ 0.732,0.732,0.732,
/* 254 */ 0.866,0.866,0.866,
/* 255 */ 1,1,1
};

35
src/osgPlugins/dxf/aci.h Normal file
View File

@@ -0,0 +1,35 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_ACI_COLOR
#define DXF_ACI_COLOR 1
// lookup table for autocad color index
struct aci {
// some color positions
enum {
BLACK,
RED,
YELLOW,
GREEN,
CYAN,
BLUE,
MAGENTA,
WHITE,
USER_2,
USER_3,
BYLAYER = 256,
MIN = 1,
MAX = 255
};
static double table[256*3];
};
#endif

View File

@@ -0,0 +1,50 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_CODE_VALUE
#define DXF_CODE_VALUE 1
#include <string>
/// a group code / value pair handler
/// to do: write accessors which check for the correct value
/// being asked for (each group code has a value type
/// associated with it).
class codeValue {
public:
codeValue() { reset(); }
void reset()
{
_groupCode = -100;
_type = 0;
_bool = false;
_short = 0;
_int = 0;
_long = 0;
_double = 0;
_string = "";
}
int _groupCode;
int _type;
std::string _unknown;
std::string _string;
bool _bool;
unsigned short _short;
int _int;
long _long;
double _double;
};
typedef std::vector<codeValue> VariableList; // this may be too big, find another way
#endif

View File

@@ -0,0 +1,58 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfBlock.h"
#include "dxfFile.h"
#include "codeValue.h"
#include "dxfEntity.h"
using namespace std;
void
dxfBlock::assign(dxfFile* dxf, codeValue& cv)
{
string s = cv._string;
if (cv._groupCode == 0) {
if (_currentEntity && _currentEntity->done()) {
_currentEntity = new dxfEntity(s);
_entityList.push_back(_currentEntity);
} else if (_currentEntity) {
_currentEntity->assign(dxf, cv);
} else {
_currentEntity = new dxfEntity(s);
_entityList.push_back(_currentEntity);
}
} else if (_currentEntity) {
_currentEntity->assign(dxf, cv);
} else if (cv._groupCode != 0) {
double d = cv._double;
switch (cv._groupCode) {
case 2:
_name = s;
case 10:
_position.x() = d;
break;
case 20:
_position.y() = d;
break;
case 30:
_position.z() = d;
break;
default:
// dxf garble
break;
}
}
}
const osg::Vec3d& dxfBlock::getPosition() const { return _position; }

View File

@@ -0,0 +1,43 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_BLOCK
#define DXF_BLOCK 1
#include <map>
#include <vector>
#include <string>
#include <osg/Referenced>
#include <osg/Vec3d>
class dxfFile;
class codeValue;
class dxfEntity;
class dxfBlock : public osg::Referenced
{
public:
dxfBlock() : _currentEntity(NULL) {}
virtual ~dxfBlock() {}
inline const std::string& getName() const { return _name; }
virtual void assign(dxfFile* dxf, codeValue& cv);
std::vector<dxfEntity*> getEntityList() { return _entityList; }
const osg::Vec3d& getPosition() const;
protected:
std::vector<dxfEntity*> _entityList;
dxfEntity* _currentEntity;
std::string _name;
osg::Vec3d _position;
};
#endif

View File

@@ -0,0 +1,88 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_DATATYPES
#define DXF_DATATYPES 1
#include <osg/Group>
typedef std::map<std::string, osg::ref_ptr<osg::Group> > LayerTable;
class dxfDataType {
public:
enum TYPE {
UNKNOWN,
STRING,
HEX,
BOOL,
SHORT,
INT,
LONG,
DOUBLE
};
inline static bool between(int a, int m, int x) { return (a >= m && a <= x); }
inline static int typeForCode(int gc) {
if ( between(gc, 0, 9) ||
gc == 100 || gc == 102 ||
between(gc, 300, 309) ||
between(gc, 410, 419) ||
between(gc, 430, 439) ||
between(gc, 470, 479) ||
gc == 999 ||
between(gc, 1000, 1009)
)
return STRING;
else if ( gc == 105 ||
between(gc, 310, 319) ||
between(gc, 320, 329) ||
between(gc, 330, 369) ||
between(gc, 390, 399)
)
return HEX;
else if ( between(gc, 290, 299 ) )
return BOOL;
else if ( between(gc, 60, 79) ||
between(gc, 170, 179) ||
between(gc, 270, 279) ||
between(gc, 280, 289) ||
between(gc, 370, 379) ||
between(gc, 380, 389) ||
between(gc, 400, 409)
)
return SHORT;
else if ( between(gc, 90, 99) ||
between(gc, 450, 459) ||
between(gc, 1060, 1070)
)
return LONG;
else if ( between(gc, 420, 429) ||
between(gc, 440, 449) ||
gc == 1071
)
return INT;
else if ( between(gc, 10, 39) ||
between(gc, 40, 59) ||
between(gc, 110, 119) ||
between(gc, 120, 129) ||
between(gc, 130, 139) ||
between(gc, 140, 149) ||
between(gc, 210, 239) ||
between(gc, 460, 469) ||
between(gc, 1010, 1019)
)
return DOUBLE;
else
return UNKNOWN;
}
};
#endif

View File

@@ -0,0 +1,805 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfEntity.h"
#include "dxfFile.h"
#include "scene.h"
#include "dxfBlock.h"
#include "codeValue.h"
using namespace std;
using namespace osg;
// static
std::map<std::string, ref_ptr<dxfBasicEntity> > dxfEntity::_registry;
RegisterEntityProxy<dxf3DFace> g_dxf3DFace;
RegisterEntityProxy<dxfCircle> g_dxfCircle;
RegisterEntityProxy<dxfArc> g_dxfArc;
RegisterEntityProxy<dxfLine> g_dxfLine;
RegisterEntityProxy<dxfVertex> g_dxfVertex;
RegisterEntityProxy<dxfPolyline> g_dxfPolyline;
RegisterEntityProxy<dxfLWPolyline> g_dxfLWPolyline;
RegisterEntityProxy<dxfInsert> g_dxfInsert;
void
dxfBasicEntity::assign(dxfFile* dxf, codeValue& cv)
{
switch (cv._groupCode) {
case 8:
_layer = cv._string;
break;
case 62:
_color = cv._short;
break;
}
}
void
dxf3DFace::assign(dxfFile* dxf, codeValue& cv)
{
double d = cv._double;
switch (cv._groupCode) {
case 10:
case 11:
case 12:
case 13:
_vertices[cv._groupCode - 10].x() = d;
break;
case 20:
case 21:
case 22:
case 23:
_vertices[cv._groupCode - 20].y() = d;
break;
case 30:
case 31:
case 32:
case 33:
_vertices[cv._groupCode - 30].z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxf3DFace::drawScene(scene* sc)
{
std::vector<Vec3d> vlist;
short nfaces = 3;
// Hate to do that, but hey, that's written in the DXF specs:
if (_vertices[2] != _vertices[3]) nfaces = 4;
for (short i = nfaces-1; i >= 0; i--)
vlist.push_back(_vertices[i]);
if (nfaces == 3) {
// to do make sure we're % 3
sc->addTriangles(getLayer(), _color, vlist);
} else if (nfaces == 4) {
// to do make sure we're % 4
sc->addQuads(getLayer(), _color, vlist);
}
}
void
dxfVertex::assign(dxfFile* dxf, codeValue& cv)
{
double d = cv._double;
unsigned short s = cv._short;
switch (cv._groupCode) {
case 10:
_vertex.x() = d;
break;
case 20:
_vertex.y() = d;
break;
case 30:
_vertex.z() = d;
break;
case 71:
_indice1 = s;
break;
case 72:
_indice2 = s;
break;
case 73:
_indice3 = s;
break;
case 74:
_indice4 = s;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxfCircle::assign(dxfFile* dxf, codeValue& cv)
{
double d = cv._double;
unsigned short s = cv._short;
switch (cv._groupCode) {
case 10:
_center.x() = d;
break;
case 20:
_center.y() = d;
break;
case 30:
_center.z() = d;
break;
case 40:
_radius = d;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxfCircle::drawScene(scene* sc)
{
Matrix m;
getOCSMatrix(_ocs, m);
sc->ocs(m);
std::vector<Vec3d> vlist;
int numsteps = 360/5; // baaarghf.
double angle_step = osg::DegreesToRadians((double)360.0 / (double) numsteps);
double angle1 = 0.0f;
double angle2 = 0.0f;
Vec3d a = _center;
Vec3d b,c;
for (int r = 0; r < numsteps; r++)
{
angle1 = angle2;
if (r == numsteps - 1)
angle2 = 0.0f;
else
angle2 += angle_step;
b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) cos(angle1), 0);
c = a + Vec3d(_radius * (double) sin(angle2), _radius * (double) cos(angle2), 0);
// vlist.push_back(a);
vlist.push_back(b);
vlist.push_back(c);
}
sc->addLineStrip(getLayer(), _color, vlist);
// sc->addTriangles(getLayer(), _color, vlist);
sc->ocs_clear();
}
void
dxfArc::assign(dxfFile* dxf, codeValue& cv)
{
double d = cv._double;
unsigned short s = cv._short;
switch (cv._groupCode) {
case 10:
_center.x() = d;
break;
case 20:
_center.y() = d;
break;
case 30:
_center.z() = d;
break;
case 40:
_radius = d;
break;
case 50:
_startAngle = d;
break;
case 51:
_endAngle = d;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxfArc::drawScene(scene* sc)
{
Matrix m;
getOCSMatrix(_ocs, m);
sc->ocs(m);
std::vector<Vec3d> vlist;
double end;
double start;
if (_startAngle > _endAngle) {
start = _startAngle;
end = _endAngle + 360;
} else {
start = _startAngle;
end = _endAngle;
}
double angle_step = DegreesToRadians(end - start);
int numsteps = (end - start)/5; // hurmghf. say 5 degrees?
if (numsteps * 5 < (end - start)) numsteps++;
angle_step /= (double) numsteps;
end = DegreesToRadians((-_startAngle)+90.0);
start = DegreesToRadians((-_endAngle)+90.0);
double angle1 = 0.0f;
double angle2 = (start);
Vec3d a = _center;
Vec3d b,c;
for (int r = 0; r < numsteps; r++)
{
angle1 = angle2;
angle2 = angle1 + angle_step;
b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) cos(angle1), 0);
c = a + Vec3d(_radius * (double) sin(angle2), _radius * (double) cos(angle2), 0);
vlist.push_back(b);
vlist.push_back(c);
}
sc->addLineStrip(getLayer(), _color, vlist);
sc->ocs_clear();
}
void
dxfLine::assign(dxfFile* dxf, codeValue& cv)
{
double d = cv._double;
unsigned short s = cv._short;
switch (cv._groupCode) {
case 10:
_a.x() = d;
break;
case 20:
_a.y() = d;
break;
case 30:
_a.z() = d;
break;
case 11:
_b.x() = d;
break;
case 21:
_b.y() = d;
break;
case 31:
_b.z() = d;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxfLine::drawScene(scene* sc)
{
Matrix m;
getOCSMatrix(_ocs, m);
// don't know why this doesn't work
// sc->ocs(m);
sc->addLine(getLayer(), _color, _b, _a);
static long lcount = 0;
// std::cout << ++lcount << " ";
// sc->ocs_clear();
}
void
dxfPolyline::assign(dxfFile* dxf, codeValue& cv)
{
string s = cv._string;
if (cv._groupCode == 0) {
if (s == "VERTEX") {
_currentVertex = new dxfVertex;
if (_mcount && (_flag & 64) && _vertices.size() == _mcount) {
_indices.push_back(_currentVertex);
} else {
// don't know if and what to do if no _mcount
_vertices.push_back(_currentVertex);
}
} else {
// hum not sure if
// 1) that is possible
// 2) what to do...
}
} else if (_currentVertex) {
_currentVertex->assign(dxf, cv);
} else {
double d = cv._double;
switch (cv._groupCode) {
case 10:
// dummy
break;
case 20:
// dummy
break;
case 30:
_elevation = d; // what is elevation?
break;
case 70:
_flag = cv._short;
break;
case 71:
_mcount = cv._short;
break;
case 72:
_ncount = cv._short;
break;
case 73:
_mdensity = cv._short;
break;
case 74:
_ndensity = cv._short;
break;
case 75:
_surfacetype = cv._short;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
}
void
dxfPolyline::drawScene(scene* sc)
{
// if (getLayer() != "UDF2" && getLayer() != "ENGINES") return;
// if (!(_flag & 16)) return;
Matrix m;
getOCSMatrix(_ocs, m);
sc->ocs(m);
std::vector<Vec3d> vlist;
std::vector<Vec3d> qlist;
Vec3d a, b, c, d;
bool invert_order = false;
if (_flag & 16) {
std::vector<Vec3d> nlist;
Vec3d nr;
bool nset = false;
dxfVertex* v = NULL;
unsigned short ncount;
unsigned short mcount;
if (_surfacetype ==6) {
// I dont have examples of type 5 and 8, but they may be the same as 6
mcount = _mdensity;
ncount = _ndensity;
} else {
mcount = _mcount;
ncount = _ncount;
}
for (unsigned short n = 0; n < ncount-1; n++) {
for (unsigned short m = 1; m < mcount; m++) {
// 0
a = _vertices[(m-1)*ncount+n].get()->getVertex();
// 1
b = _vertices[m*ncount+n].get()->getVertex();
// 3
c = _vertices[(m)*ncount+n+1].get()->getVertex();
// 2
d = _vertices[(m-1)*ncount+n+1].get()->getVertex();
if (a == b ) {
vlist.push_back(a);
vlist.push_back(c);
vlist.push_back(d);
b = c;
c = d;
} else if (c == d) {
vlist.push_back(a);
vlist.push_back(b);
vlist.push_back(c);
} else {
qlist.push_back(a);
qlist.push_back(b);
qlist.push_back(c);
qlist.push_back(d);
}
if (!nset) {
nset = true;
nr = (b - a) ^ (c - a);
nr.normalize();
}
nlist.push_back(a);
}
}
if (_flag & 1) {
for (unsigned short n = 0; n < ncount-1; n++) {
// 0
a = _vertices[(mcount-1)*ncount+n].get()->getVertex();
// 1
b = _vertices[0*ncount+n].get()->getVertex();
// 3
c = _vertices[(0)*ncount+n+1].get()->getVertex();
// 2
d = _vertices[(mcount-1)*ncount+n+1].get()->getVertex();
if (a == b ) {
vlist.push_back(a);
vlist.push_back(c);
vlist.push_back(d);
b = c;
c = d;
} else if (c == d) {
vlist.push_back(a);
vlist.push_back(b);
vlist.push_back(c);
} else {
qlist.push_back(a);
qlist.push_back(b);
qlist.push_back(c);
qlist.push_back(d);
}
nlist.push_back(a);
}
}
if (_flag & 32) {
for (unsigned short m = 1; m < mcount; m++) {
// 0
a = _vertices[(m-1)*ncount+(ncount-1)].get()->getVertex();
// 1
b = _vertices[m*ncount+(ncount-1)].get()->getVertex();
// 3
c = _vertices[(m)*ncount].get()->getVertex();
// 2
d = _vertices[(m-1)*ncount].get()->getVertex();
if (a == b ) {
vlist.push_back(a);
vlist.push_back(c);
vlist.push_back(d);
b = c;
c = d;
} else if (c == d) {
vlist.push_back(a);
vlist.push_back(b);
vlist.push_back(c);
} else {
qlist.push_back(a);
qlist.push_back(b);
qlist.push_back(c);
qlist.push_back(d);
}
nlist.push_back(a);
}
}
// a naive attempt to determine vertex ordering
VList::iterator itr = nlist.begin();
Vec3d lastn = (*itr++);
double bad_c = 0;
double good_c = 0;
long bad=0,good=0;
for (; itr != nlist.end(); ) {
++itr;
if ((*itr)== lastn) continue;
Vec3d diff = ((*itr)-lastn);
diff.normalize();
float dot = diff * nr;
if (dot > 0.0) {
bad_c += dot;
++bad;
} else {
++good;
good_c += dot;
}
}
if (bad > good) {
invert_order = true;
}
if (qlist.size())
sc->addQuads(getLayer(), _color, qlist, invert_order);
if (vlist.size())
sc->addTriangles(getLayer(), _color, vlist, invert_order);
} else if (_flag & 64) {
if (_ncount > _indices.size())
_ncount = _indices.size();
unsigned short _facetype = 3;
unsigned short count = 0;
for (unsigned short i = 0; i < _ncount; i++) {
dxfVertex* vindice = _indices[i].get();
if (!vindice) continue;
dxfVertex* v = NULL;
if (vindice->getIndice4()) {
_facetype = 4;
d = _vertices[vindice->getIndice4()-1].get()->getVertex();
} else {
_facetype = 3;
}
if (vindice->getIndice3()) {
c = _vertices[vindice->getIndice3()-1].get()->getVertex();
} else {
c = _vertices[count++].get()->getVertex();
}
if (vindice->getIndice2()) {
b = _vertices[vindice->getIndice2()-1].get()->getVertex();
} else {
b = _vertices[count++].get()->getVertex();
}
if (vindice->getIndice1()) {
a = _vertices[vindice->getIndice1()-1].get()->getVertex();
} else {
a = _vertices[count++].get()->getVertex();
}
if (_facetype == 4) {
qlist.push_back(d);
qlist.push_back(c);
qlist.push_back(b);
qlist.push_back(a);
} else {
qlist.push_back(c);
qlist.push_back(b);
qlist.push_back(a);
}
}
if (vlist.size())
sc->addTriangles(getLayer(), _color, vlist);
if (qlist.size())
sc->addQuads(getLayer(), _color, qlist);
// is there a flag 1 or 32 for 64?
} else {
// simple polyline?
for (short i = _vertices.size()-1; i >= 0; i--)
vlist.push_back(_vertices[i]->getVertex());
if (_flag & 1) {
// std::cout << "line loop " << _vertices.size() << std::endl;
sc->addLineLoop(getLayer(), _color, vlist);
} else {
// std::cout << "line strip " << _vertices.size() << std::endl;
sc->addLineStrip(getLayer(), _color, vlist);
}
}
sc->ocs_clear();
}
void
dxfLWPolyline::assign(dxfFile* dxf, codeValue& cv)
{
string s = cv._string;
double d = cv._double;
switch (cv._groupCode) {
case 10:
_lastv.x() = d;
// x
break;
case 20:
_lastv.y() = d;
_lastv.z() = _elevation;
_vertices.push_back ( _lastv );
// y -> on shoot
break;
case 38:
_elevation = d; // what is elevation?
break;
case 70:
_flag = cv._short;
break;
case 90:
_vcount = cv._short;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
void
dxfLWPolyline::drawScene(scene* sc)
{
// if (getLayer() != "UDF2" && getLayer() != "ENGINES") return;
// if (!(_flag & 16)) return;
Matrix m;
getOCSMatrix(_ocs, m);
sc->ocs(m);
if (_flag & 1) {
// std::cout << "lwpolyline line loop " << _vertices.size() << std::endl;
sc->addLineLoop(getLayer(), _color, _vertices);
} else {
// std::cout << "lwpolyline line strip " << _vertices.size() << std::endl;
sc->addLineStrip(getLayer(), _color, _vertices);
}
sc->ocs_clear();
}
void
dxfInsert::assign(dxfFile* dxf, codeValue& cv)
{
string s = cv._string;
if (_done || (cv._groupCode == 0 && s != "INSERT")) {
_done = true;
return;
}
if (cv._groupCode == 2 && !_block) {
_blockName = s;
_block = dxf->findBlock(s);
} else {
double d = cv._double;
switch (cv._groupCode) {
case 10:
_point.x() = d;
break;
case 20:
_point.y() = d;
break;
case 30:
_point.z() = d;
break;
case 41:
_scale.x() = d;
break;
case 42:
_scale.y() = d;
break;
case 43:
_scale.z() = d;
break;
case 50:
_rotation = d;
break;
case 210:
_ocs.x() = d;
break;
case 220:
_ocs.y() = d;
break;
case 230:
_ocs.z() = d;
break;
default:
dxfBasicEntity::assign(dxf, cv);
break;
}
}
}
/// hum. read the doc, then come back here. then try to figure.
void
dxfInsert::drawScene(scene* sc)
{
// INSERTs can be nested. So pull the current matrix
// and push it back after we fill our context
// This is a snapshot in time. I will rewrite all this to be cleaner,
// but for now, it seems working fine
// (with the files I have, the results are equal to Voloview,
// and better than Deep Exploration and Lightwave).
Matrixd back = sc->backMatrix();
Matrixd m;
m.makeIdentity();
sc->pushMatrix(m, true);
Vec3d trans = _block->getPosition();
sc->blockOffset(-trans);
if (_rotation) {
sc->pushMatrix(Matrixd::rotate(osg::DegreesToRadians(_rotation), 0,0,1));
}
sc->pushMatrix(Matrixd::scale(_scale.x(), _scale.y(), _scale.z()));
sc->pushMatrix(Matrix::translate(_point.x(), _point.y(), _point.z()));
getOCSMatrix(_ocs, m);
sc->pushMatrix(m);
sc->pushMatrix(back);
std::vector<dxfEntity*> l = _block->getEntityList();
for (std::vector<dxfEntity*>::iterator itr = l.begin(); itr != l.end(); ++itr) {
dxfBasicEntity* e = (*itr)->getEntity();
if (e) {
e->drawScene(sc);
}
}
sc->popMatrix(); // ocs
sc->popMatrix(); // translate
sc->popMatrix(); // scale
if (_rotation) {
sc->popMatrix(); // rotate
}
sc->popMatrix(); // identity
sc->popMatrix(); // back
sc->blockOffset(Vec3d(0,0,0));
}
// static
void
dxfEntity::registerEntity(dxfBasicEntity* entity)
{
_registry[entity->name()] = entity;
}
// static
void
dxfEntity::unregisterEntity(dxfBasicEntity* entity)
{
map<string, ref_ptr<dxfBasicEntity > >::iterator itr = _registry.find(entity->name());
if (itr != _registry.end()) {
_registry.erase(itr);
}
}
void dxfEntity::drawScene(scene* sc)
{
for (std::vector<ref_ptr<dxfBasicEntity > >::iterator itr = _entityList.begin();
itr != _entityList.end(); ++itr) {
(*itr)->drawScene(sc);
}
}
void
dxfEntity::assign(dxfFile* dxf, codeValue& cv)
{
string s = cv._string;
if (cv._groupCode == 66 && !(_entity && string("TABLE") == _entity->name())) {
// The funny thing here. Group code 66 has been called 'obsoleted'
// for a POLYLINE. But not for an INSERT. Moreover, a TABLE
// can have a 66 for... an obscure bottom cell color value.
// I decided to rely on the presence of the 66 code for
// the POLYLINE. If you find a better alternative,
// contact me, or correct this code
// and post the correction to osg mailing list
_seqend = true;
} else if (_seqend && cv._groupCode == 0 && s == "SEQEND") {
_seqend = false;
// cout << "... off" << endl;
} else if (_entity) {
_entity->assign(dxf, cv);
}
}

View File

@@ -0,0 +1,308 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_ENTITY
#define DXF_ENTITY 1
#include <vector>
#include <string>
#include <iostream>
#include <osg/Referenced>
#include <osg/ref_ptr>
#include <osg/Array>
#include <osg/Vec3d>
#include <osg/Node>
#include <osg/Matrix>
class scene;
class dxfBlock;
class codeValue;
class dxfFile;
static inline void
getOCSMatrix(osg::Vec3d ocs, osg::Matrix &m)
{
static const double one_64th = 1.0/64.0;
m.makeIdentity();
if (ocs == osg::Vec3d(0,0,1)) return;
osg::Vec3d ax(1,0,0), ay(0,1,0), az(0,0,1);
osg::Vec3d ocsaxis(ocs);
ocsaxis.normalize();
if (fabs(ocsaxis.x()) < one_64th && fabs(ocsaxis.y()) < one_64th) {
ax = ay ^ ocsaxis;
} else {
ax = az ^ ocsaxis;
}
ax.normalize();
ay = ocsaxis ^ ax;
ay.normalize();
m = osg::Matrix( ax.x(), ax.y(), ax.z(), 0,
ay.x(), ay.y(), ay.z(), 0,
ocsaxis.x(), ocsaxis.y(), ocsaxis.z(), 0,
0,0,0,1);
// m = m.inverse(m);
}
class dxfBasicEntity : public osg::Referenced
{
public:
dxfBasicEntity() : _color(0) {}
virtual ~dxfBasicEntity() {}
virtual dxfBasicEntity* create() = 0;
virtual const char* name() = 0;
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc) {}
const std::string getLayer() const { return _layer; }
protected:
std::string _layer;
unsigned short _color;
};
class dxfCircle : public dxfBasicEntity
{
public:
dxfCircle() : _radius(0), _ocs(0,0,1) {}
virtual ~dxfCircle() {}
virtual dxfBasicEntity* create() { return new dxfCircle; }
virtual const char* name() { return "CIRCLE"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
osg::Vec3d _center;
double _radius;
osg::Vec3d _ocs;
};
class dxfArc : public dxfBasicEntity
{
public:
dxfArc() : _radius(0), _startAngle(0), _endAngle(360), _ocs(0,0,1) {}
virtual ~dxfArc() {}
virtual dxfBasicEntity* create() { return new dxfArc; }
virtual const char* name() { return "ARC"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
osg::Vec3d _center;
double _radius;
double _startAngle;
double _endAngle;
osg::Vec3d _ocs;
};
class dxfLine : public dxfBasicEntity
{
public:
dxfLine() : _ocs(0,0,1) {}
virtual ~dxfLine() {}
virtual dxfBasicEntity* create() { return new dxfLine; }
virtual const char* name() { return "LINE"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
osg::Vec3d _a;
osg::Vec3d _b;
osg::Vec3d _ocs;
};
class dxf3DFace : public dxfBasicEntity
{
public:
dxf3DFace()
{
_vertices[0] = osg::Vec3d(0,0,0);
_vertices[1] = osg::Vec3d(0,0,0);
_vertices[2] = osg::Vec3d(0,0,0);
_vertices[3] = osg::Vec3d(0,0,0);
}
virtual ~dxf3DFace() {}
virtual dxfBasicEntity* create() { return new dxf3DFace; }
virtual const char* name() { return "3DFACE"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
osg::Vec3d _vertices[4];
};
class dxfVertex : public dxfBasicEntity
{
public:
dxfVertex() : _vertex(osg::Vec3d(0,0,0)), _indice1(0), _indice2(0), _indice3(0), _indice4(0) {}
virtual ~dxfVertex() {}
virtual dxfBasicEntity* create() { return new dxfVertex; }
virtual const char* name() { return "VERTEX"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
void getVertex(double &x, double &y, double &z) { x=_vertex.x();y=_vertex.y();z=_vertex.z(); }
const osg::Vec3d& getVertex() const { return _vertex; }
const unsigned short getIndice1() const { return _indice1; }
const unsigned short getIndice2() const { return _indice2; }
const unsigned short getIndice3() const { return _indice3; }
const unsigned short getIndice4() const { return _indice4; }
protected:
osg::Vec3d _vertex;
unsigned short _indice1, _indice2, _indice3, _indice4;
};
class dxfPolyline : public dxfBasicEntity
{
public:
dxfPolyline() : _currentVertex(NULL),
_elevation(0.0),
_flag(0),
_mcount(0),
_ncount(0),
_nstart(0),
_nend(0),
_ocs(osg::Vec3d(0,0,1)),
_mdensity(0),
_ndensity(0),
_surfacetype(0)
{}
virtual ~dxfPolyline() {}
virtual dxfBasicEntity* create() { return new dxfPolyline; }
virtual const char* name() { return "POLYLINE"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual int vertexCount() { return _vertices.size(); }
virtual void drawScene(scene* sc);
protected:
dxfVertex* _currentVertex;
std::vector<osg::ref_ptr<dxfVertex> > _vertices;
std::vector<osg::ref_ptr<dxfVertex> > _indices;
double _elevation;
unsigned short _flag;
unsigned short _mcount;
unsigned short _ncount;
unsigned short _nstart; // 71
unsigned short _nend; //72
osg::Vec3d _ocs; //210 220 230
unsigned short _mdensity; // 73
unsigned short _ndensity; // 74
unsigned short _surfacetype; //75
};
class dxfLWPolyline : public dxfBasicEntity
{
public:
dxfLWPolyline() : _elevation(0.0),
_flag(0),
_vcount(0),
_ocs(osg::Vec3d(0,0,1)),
_lastv(0,0,0)
{}
virtual ~dxfLWPolyline() {}
virtual dxfBasicEntity* create() { return new dxfLWPolyline; }
virtual const char* name() { return "LWPOLYLINE"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual int vertexCount() { return _vertices.size(); }
virtual void drawScene(scene* sc);
protected:
osg::Vec3d _lastv;
std::vector< osg::Vec3d > _vertices;
double _elevation;
unsigned short _flag;
unsigned short _vcount; // 90
osg::Vec3d _ocs; //210 220 230
};
class dxfInsert : public dxfBasicEntity
{
public:
dxfInsert() : _block(NULL),
_done(false),
_rotation(0),
_scale(1,1,1),
_point(osg::Vec3d(0,0,0)),
_ocs(osg::Vec3d(0,0,1)) {}
virtual ~dxfInsert() {}
virtual dxfBasicEntity* create() { return new dxfInsert; }
virtual const char* name() { return "INSERT"; }
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
std::string _blockName;
osg::ref_ptr<dxfBlock> _block;
bool _done; // since we are on a SEQEND, we must
// make sure not getting values addressed to other
// entities (dxf garble things) in the sequence
double _rotation;
osg::Vec3d _scale;
osg::Vec3d _point;
osg::Vec3d _ocs;
};
class dxfEntity : public osg::Referenced
{
public:
dxfEntity(std::string s) : _entity(NULL), _seqend(false)
{
_entity = findByName(s);
if (_entity) {
_entityList.push_back(_entity);
// std::cout << "entity " << s << std::endl;
}
}
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual bool done() { return !_seqend; }
static void registerEntity(dxfBasicEntity*);
static void unregisterEntity(dxfBasicEntity*);
static dxfBasicEntity* findByName(std::string s)
{
dxfBasicEntity* be = _registry[s].get();
if (be)
return be->create();
else {
std::cout << " no " << s << std::endl;
return NULL;
}
}
virtual void drawScene(scene* sc);
dxfBasicEntity* getEntity() { return _entity; }
protected:
std::vector<osg::ref_ptr<dxfBasicEntity> > _entityList;
static std::map<std::string, osg::ref_ptr<dxfBasicEntity> > _registry;
dxfBasicEntity* _entity;
bool _seqend; // bypass 0 codes. needs a 0 seqend to close.
};
/** Proxy class for automatic registration of dxf entities reader/writers.*/
template<class T>
class RegisterEntityProxy
{
public:
RegisterEntityProxy()
{
_rw = new T;
dxfEntity::registerEntity(_rw.get());
}
~RegisterEntityProxy()
{
dxfEntity::unregisterEntity(_rw.get());
}
T* get() { return _rw.get(); }
protected:
osg::ref_ptr<T> _rw;
};
#endif

View File

@@ -0,0 +1,120 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfFile.h"
#include "dxfReader.h"
#include "dxfBlock.h"
#include "dxfEntity.h"
#include "dxfDataTypes.h"
#include "scene.h"
#include "codeValue.h"
#include <osg/Group>
using namespace std;
bool
dxfFile::parseFile()
{
if (_fileName == "") return false;
_reader = new dxfReader;
if (_reader->openFile(_fileName)) {
codeValue cv;
while(_reader->nextGroupCode(cv)) {
short result = assign(cv);
if (result < 0)
return false;
else if (result == 0) {
return true;
}
}
// we did not reach 0 EOF
return false;
} else {
return false;
}
}
osg::Group*
dxfFile::dxf2osg()
{
if (!_entities) return NULL;
if (!_tables) { // a dxfTable is needed to create undefined layers
_tables = new dxfTables;
}
osg::ref_ptr<dxfLayerTable> layerTable = _tables->getOrCreateLayerTable();
// to do: should be more general and pass a pointer to ourselves
// which in turn should be able to feed any information
// the scene might need
_scene = new scene(layerTable.get());
_entities->drawScene(_scene.get());
osg::Group* g = _scene->scene2osg();
return g;
}
dxfBlock*
dxfFile::findBlock(std::string name)
{
if (_blocks.get())
return _blocks->findBlock(name);
return NULL;
}
/// not used. if you want to know what a header variable
/// contains, call this. pass the complete variable name
/// including "$", for example: "$EXTMAX"
VariableList
dxfFile::getVariable(std::string var)
{
return _header->getVariable(var);
}
/// parse the dxf sections
short
dxfFile::assign(codeValue& cv)
{
std::string s = cv._string;
if (cv._groupCode == 0 && s == std::string("ENDSEC")) {
_isNewSection = false;
_current = _unknown.get();
} else if (cv._groupCode == 0 && s == std::string("SECTION")) {
_isNewSection = true;
} else if (cv._groupCode == 0 && s == std::string("EOF")) {
return 0;
} else if (cv._groupCode == 2 && _isNewSection) {
_isNewSection = false;
// std::cout << "Reading section " << s << std::endl;
if (s =="HEADER") {
_header = new dxfHeader;
_current = _header.get();
} else if (s =="TABLES") {
_tables = new dxfTables;
_current = _tables.get();
} else if (s =="BLOCKS") {
_blocks = new dxfBlocks;
_current = _blocks.get();
} else if (s =="ENTITIES") {
_entities = new dxfEntities;
_current = _entities.get();
} else {
_current = _unknown.get();
}
} else if (_isNewSection) {
// problem. a 0/SECTION should be followed by a 2/SECTION_NAME
std::cout << "No groupcode for changing section " << cv._groupCode << " value: " << s << std::endl;
return -1;
} else if (_current.get()) {
_current->assign(this, cv);
}
return 1;
}

View File

@@ -0,0 +1,59 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_FILE
#define DXF_FILE 1
#include <osg/Group>
#include <iostream>
#include <string>
#include "dxfSectionBase.h"
#include "dxfReader.h"
#include "dxfSection.h"
#include "codeValue.h"
class dxfHeader;
class dxfTables;
class dxfBlocks;
class dxfEntities;
class dxfSection;
class scene;
class dxfBlock;
class dxfFile {
public:
dxfFile(std::string fileName) :
_fileName(fileName),
_isNewSection(false)
{}
bool parseFile();
osg::Group* dxf2osg();
dxfBlock* findBlock(std::string name);
VariableList getVariable(std::string var);
protected:
short assign(codeValue& cv);
std::string _fileName;
bool _isNewSection;
osg::ref_ptr<dxfReader> _reader;
osg::ref_ptr<dxfSection> _current;
osg::ref_ptr<dxfHeader> _header;
osg::ref_ptr<dxfTables> _tables;
osg::ref_ptr<dxfBlocks> _blocks;
osg::ref_ptr<dxfEntities> _entities;
osg::ref_ptr<dxfSection> _unknown;
osg::ref_ptr<scene> _scene;
};
#endif

View File

@@ -0,0 +1,204 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfReader.h"
#include "dxfDataTypes.h"
#include "codeValue.h"
#include <map>
#include <vector>
#include <iostream>
#include <utility>
#include <sstream>
#include <math.h>
#include <iomanip>
using namespace std;
static
std::string
trim(const string& str)
{
if (!str.size()) return str;
string::size_type first = str.find_first_not_of(" \t");
string::size_type last = str.find_last_not_of(" \t\r\n");
return str.substr(first, last-first+1);
}
/*
************** readerBase
*/
bool readerBase::readGroup(std::ifstream& f, codeValue& cv)
{
cv.reset();
if (readGroupCode(f, cv._groupCode)) {
cv._type = dxfDataType::typeForCode(cv._groupCode);
switch (cv._type) {
case dxfDataType::BOOL:
return readValue(f, cv._bool);
break;
case dxfDataType::SHORT:
return readValue(f, cv._short);
break;
case dxfDataType::INT:
return readValue(f, cv._int);
break;
case dxfDataType::LONG:
return readValue(f, cv._long);
break;
case dxfDataType::DOUBLE:
return readValue(f, cv._double);
break;
case dxfDataType::UNKNOWN:
case dxfDataType::STRING:
case dxfDataType::HEX:
default: // to do: default case an error
return readValue(f, cv._string);
break;
}
} else {
cv._type = dxfDataType::UNKNOWN;
cv._groupCode = -1;
}
return false;
}
/*
************** readerText
*/
bool readerText::success(bool inSuccess, string type)
{
if (!inSuccess)
cout << "Error converting line " << _lineCount << " to type " << type << endl;
return inSuccess;
}
bool readerText::getTrimmedLine(std::ifstream& f)
{
static string line = "";
if (getline(f, line, _delim)) {
++_lineCount;
_str.clear();
_str.str(trim(line));
return true;
}
return false;
}
bool readerText::readGroupCode(std::ifstream& f, int &groupcode)
{
if (getTrimmedLine(f)) {
_str >> groupcode;
return success(!_str.fail(), "int");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, string &s)
{
if (getTrimmedLine(f)) {
getline(_str, s);
// empty string is valid
return success((!_str.fail() || s == ""), "string");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, bool &b)
{
if (getTrimmedLine(f)) {
_str >> b;
return success(!_str.fail(), "bool");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, unsigned short &s)
{
if (getTrimmedLine(f)) {
_str >> s;
return success(!_str.fail(), "unsigned short");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, int &i)
{
if (getTrimmedLine(f)) {
_str >> i;
return success(!_str.fail(), "int");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, long &l)
{
if (getTrimmedLine(f)) {
_str >> l;
return success(!_str.fail(), "long");
} else {
return false;
}
}
bool readerText::readValue(std::ifstream& f, double &d)
{
if (getTrimmedLine(f)) {
_str >> d;
return success(!_str.fail(), "double");
} else {
return false;
}
}
/*
************** dxfReader
*/
bool
dxfReader::openFile(std::string fileName)
{
if (fileName.size() == 0) return false;
_ifs.open(fileName.c_str(), ios::binary); // found mac autocad with \r delimiters
if (!_ifs) {
cout << " Can't open " << fileName << endl;
return false;
}
// A binary file starts with "AutoCAD Binary DXF<CR><LF><SUB><NULL>"
char buf[255];
_ifs.get(buf, 255);
string sentinel(buf);
if (trim(sentinel) == "AutoCAD Binary DXF") {
cout << " Binary DXF not supported. For now. Come back soon." << endl;
return false;
}
string::size_type lf = sentinel.find('\n');
string::size_type cr = sentinel.find('\r');
// gossage. un mac peut mettre juste CR. ca fonctionne pas:
// if (cr > 0 && (!lf || lf > cr + 1))
// _reader = new readerText('\r');
// else
_reader = new readerText;
_ifs.seekg(0, ios::beg);
return true;
}
bool
dxfReader::nextGroupCode(codeValue& cv)
{
return (_reader->readGroup(_ifs, cv));
}

View File

@@ -0,0 +1,102 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
/* File handling.
dxfFile creates a dxfReader, which in turn create a readerText or a readerBinary
depending on file type.
*/
#ifndef DXF_READER
#define DXF_READER 1
#include <fstream>
#include <string>
#include <sstream>
#include <osg/Referenced>
#include <osg/ref_ptr>
class codeValue;
/// readerBase. abstract base class for reading a dxf file
/// and interpreting data types
class readerBase :public osg::Referenced
{
public:
readerBase() {}
virtual ~readerBase() {}
bool readGroup(std::ifstream& f, codeValue& cv);
protected:
virtual bool readGroupCode(std::ifstream& f, int &groupcode) = 0;
virtual bool readValue(std::ifstream& f, std::string &s) = 0;
virtual bool readValue(std::ifstream& f, bool &b) = 0;
virtual bool readValue(std::ifstream& f, unsigned short &s) = 0;
virtual bool readValue(std::ifstream& f, int &i) = 0;
virtual bool readValue(std::ifstream& f, long &l) = 0;
virtual bool readValue(std::ifstream& f, double &d) = 0;
};
/// readerText. convert data using stringstream.
class readerText : public readerBase
{
public:
readerText(char delim = '\n') : readerBase(), _lineCount(0), _delim(delim) {}
virtual ~readerText() {}
protected:
bool success(bool inSuccess, std::string type);
bool getTrimmedLine(std::ifstream& f);
virtual bool readGroupCode(std::ifstream& f, int &groupcode);
virtual bool readValue(std::ifstream& f, std::string &s);
virtual bool readValue(std::ifstream& f, bool &b);
virtual bool readValue(std::ifstream& f, unsigned short &s);
virtual bool readValue(std::ifstream& f, int &i);
virtual bool readValue(std::ifstream& f, long &l);
virtual bool readValue(std::ifstream& f, double &d);
std::stringstream _str;
unsigned long _lineCount;
char _delim;
};
/// readerBinary. to be implemented
class readerBinary : public readerBase
{
public:
readerBinary() : readerBase() {}
virtual ~readerBinary() {}
protected:
virtual bool readGroupCode(std::ifstream& f, int &groupcode) {}
virtual bool readValue(std::ifstream& f, std::string &s) {}
virtual bool readValue(std::ifstream& f, bool &b) {}
virtual bool readValue(std::ifstream& f, unsigned short &s) {}
virtual bool readValue(std::ifstream& f, int &i) {}
virtual bool readValue(std::ifstream& f, long &l) {}
virtual bool readValue(std::ifstream& f, double &d) {}
};
/// dxfReader. gets you through the dxf file, one group code/value pair at a time.
/// just instanciate, openFile(), then loop while(nextGroupCode())
class dxfReader : public osg::Referenced
{
public:
dxfReader() {}
virtual ~dxfReader() {}
bool openFile(std::string fileName);
bool nextGroupCode(codeValue& cv);
protected:
std::ifstream _ifs;
osg::ref_ptr<readerBase> _reader;
};
#endif

View File

@@ -0,0 +1,87 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfSection.h"
#include "dxfEntity.h"
#include "dxfBlock.h"
void dxfHeader::assign(dxfFile* dxf, codeValue& cv)
{
if (cv._groupCode == 9) {
_inVariable = true;
VariableList var;
_variables[cv._string] = var;
_currentVariable = cv._string;
} else if (_inVariable) {
VariableList& var = getVariable(_currentVariable);
var.push_back(cv);
}
}
void dxfTables::assign(dxfFile* dxf, codeValue& cv)
{
if (cv._groupCode == 0 && cv._string == "TABLE") {
_currentTable = NULL;
} else if (cv._groupCode == 2 && !_currentTable.get()) {
// treat layer table as a special case
if (cv._string == "LAYER") {
_layerTable = new dxfLayerTable;
_currentTable = _layerTable.get();
} else {
_currentTable = new dxfTable;
_others.push_back(_currentTable.get());
}
} else if (_currentTable.get()) {
_currentTable->assign(dxf, cv);
}
}
void dxfBlocks::assign(dxfFile* dxf, codeValue& cv)
{
if (cv._groupCode == 0 && cv._string == std::string("BLOCK")) {
_currentBlock = new dxfBlock;
_blockList.push_back(_currentBlock);
} else if (cv._groupCode == 0 && cv._string == std::string("ENDBLK") && _currentBlock) {
std::string bn = _currentBlock->getName();
_blockNameList[bn] = _currentBlock;
} else if (_currentBlock) {
_currentBlock->assign(dxf, cv);
}
}
void dxfEntities::assign(dxfFile* dxf, codeValue& cv)
{
if (cv._groupCode == 0) {
if (_currentEntity && _currentEntity->done()) {
_currentEntity = new dxfEntity(cv._string);
_entityList.push_back(_currentEntity);
} else if (_currentEntity) {
_currentEntity->assign(dxf, cv);
} else {
_currentEntity = new dxfEntity(cv._string);
_entityList.push_back(_currentEntity);
}
} else if (_currentEntity) {
_currentEntity->assign(dxf, cv);
}
}
void
dxfEntities::drawScene(scene* sc)
{
for (std::vector<dxfEntity*>::iterator itr = _entityList.begin();
itr != _entityList.end(); ++itr)
(*itr)->drawScene(sc);
}
dxfBlock*
dxfBlocks::findBlock(std::string s) { return _blockNameList[s]; }

View File

@@ -0,0 +1,107 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
/**
Classes used to parse each section of a DXF file. Not all
types of section has been defined here, just the ones
I found of interest, ie HEADER, TABLES, BLOCKS, and ENTITIES.
Yet to be implemented: CLASSES, OBJECTS, and THUMBNAILIMAGE.
*/
#ifndef DXF_SECTION
#define DXF_SECTION 1
#include "dxfDataTypes.h"
#include "dxfSectionBase.h"
#include "dxfFile.h"
#include "dxfTable.h"
#include "codeValue.h"
#include "scene.h"
#include <map>
#include <vector>
#include <iostream>
#include <string>
class dxfEntity;
class dxfBlock;
class dxfSection : public dxfSectionBase
{
public:
dxfSection() {}
virtual ~dxfSection() {}
};
class dxfHeader : public dxfSection
{
public:
dxfHeader() : _inVariable(false) {}
virtual ~dxfHeader() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
VariableList& getVariable(std::string inVar) { return _variables[inVar]; }
protected:
std::map<std::string, VariableList> _variables;
bool _inVariable;
std::string _currentVariable;
};
class dxfTables : public dxfSection
{
public:
dxfTables() : _inLayerTable(false) {}
virtual ~dxfTables() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
dxfLayerTable* getOrCreateLayerTable()
{
if (!_layerTable.get())
_layerTable = new dxfLayerTable;
return _layerTable.get();
}
protected:
bool _inLayerTable;
osg::ref_ptr<dxfLayerTable> _layerTable;
std::vector<osg::ref_ptr<dxfTable> > _others;
osg::ref_ptr<dxfTable> _currentTable;
};
class dxfEntities : public dxfSection
{
public:
dxfEntities() : _currentEntity(NULL) {}
virtual ~dxfEntities() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual void drawScene(scene* sc);
protected:
dxfEntity* _currentEntity;
std::vector<dxfEntity*> _entityList;
};
class dxfBlocks : public dxfSection
{
public:
dxfBlocks() : _currentBlock(NULL) {}
virtual ~dxfBlocks() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
dxfBlock* findBlock(std::string s);
protected:
dxfBlock* _currentBlock;
std::map<std::string, dxfBlock*> _blockNameList;
std::vector<dxfBlock*> _blockList;
};
#endif

View File

@@ -0,0 +1,30 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_SECTIONBASE
#define DXF_SECTIONBASE 1
#include <osg/Referenced>
class dxfFile;
class codeValue;
/// abstract base class for sections. see dxfSection.h
class dxfSectionBase : public osg::Referenced
{
public:
dxfSectionBase() {}
virtual ~dxfSectionBase() {}
virtual void assign(dxfFile* dxf, codeValue& cv) = 0;
};
#endif

View File

@@ -0,0 +1,46 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#include "dxfTable.h"
#include "dxfFile.h"
#include "codeValue.h"
void dxfLayer::assign(dxfFile* dxf, codeValue& cv)
{
switch (cv._groupCode) {
case 2:
_name = cv._string;
break;
case 62:
_color = cv._short;
if ((short)_color < 0) _frozen = true;
break;
case 70:
_frozen = (bool)(cv._short & 1);
break;
}
}
void dxfLayerTable::assign(dxfFile* dxf, codeValue& cv)
{
std::string s = cv._string;
if (cv._groupCode == 0 ) {
if (_currentLayer.get()) {
_layers[_currentLayer->getName()] = _currentLayer.get();
}
if (s == "LAYER") {
_currentLayer = new dxfLayer;
} // otherwise it's the close call from ENDTAB
} else if (_currentLayer.get()) {
_currentLayer->assign(dxf, cv);
}
}

View File

@@ -0,0 +1,75 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
#ifndef DXF_TABLE
#define DXF_TABLE 1
#include <string>
#include <map>
#include <osg/Referenced>
#include <osg/ref_ptr>
class dxfFile;
class codeValue;
// special case: the layer table
class dxfTable : public osg::Referenced
{
public:
dxfTable() {}
virtual ~dxfTable() {}
virtual void assign(dxfFile* dxf, codeValue& cv) {}
};
class dxfLayer : public osg::Referenced
{
public:
dxfLayer(std::string name = "0") : _name(name), _color(7), _frozen(false) {}
virtual ~dxfLayer() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
virtual const std::string& getName() const { return _name; }
virtual const unsigned short& getColor() const { return _color; }
virtual void setName(const std::string& name) { _name = name; }
const bool& getFrozen() const { return _frozen; }
protected:
std::string _name;
unsigned short _color;
bool _frozen;
};
class dxfLayerTable : public dxfTable
{
public:
dxfLayerTable() {}
virtual ~dxfLayerTable() {}
virtual void assign(dxfFile* dxf, codeValue& cv);
dxfLayer* findOrCreateLayer(std::string name)
{
if (name == "") name = "0"; // nowhere it is said "" is invalid, but...
dxfLayer* layer = _layers[name].get();
if (!layer) {
layer = new dxfLayer;
_layers[name] = layer;
}
return layer;
}
protected:
std::map<std::string, osg::ref_ptr<dxfLayer> > _layers;
osg::ref_ptr<dxfLayer> _currentLayer;
};
#endif

View File

@@ -0,0 +1,189 @@
/* Importation de fichiers DXF dans OpenSceneGraph (see www.openscenegraph.org)
Copyright (C) 2004 by Paul de Repentigny <pdr@grapharchitecture.com>
*/
#include "scene.h"
#include "dxfTable.h"
#include "aci.h"
using namespace osg;
using namespace std;
osg::Vec4
sceneLayer::getColor(unsigned short color)
{
// you're supposed to have a correct color in hand
unsigned short r = color * 3;
unsigned short g = color * 3 + 1;
unsigned short b = color * 3 + 2;
Vec4 c(aci::table[r], aci::table[g], aci::table[b], 1.0f);
return c;
}
scene::scene(dxfLayerTable* lt) : _layerTable(lt)
{
_m.makeIdentity();
_r.makeIdentity();
}
void
scene::setLayerTable(dxfLayerTable* lt)
{
_layerTable = lt;
}
Vec3d scene::addVertex(Vec3d v)
{
v += _t;
v = preMultd(_r, v);
osg::Matrixd m = osg::Matrix::translate(v.x(), v.y(), v.z());
m = m * _m;
Vec3d a = preMultd(m, Vec3d(0,0,0));
_b.expandBy(a);
return a;
}
Vec3d scene::addNormal(Vec3d v)
{
// to do: vertices are not always listed in order. find why.
return v;
}
void
scene::addLine(std::string l, unsigned short color, Vec3d s, Vec3d e)
{
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
if (layer->getFrozen()) return;
sceneLayer* ly = findOrCreateSceneLayer(l);
Vec3d a(addVertex(s)), b(addVertex(e));
ly->_lines[correctedColorIndex(l, color)].push_back(a);
ly->_lines[correctedColorIndex(l, color)].push_back(b);
}
void scene::addLineStrip(std::string l, unsigned short color, std::vector<Vec3d> vertices)
{
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
if (layer->getFrozen()) return;
sceneLayer* ly = findOrCreateSceneLayer(l);
std::vector<Vec3d> converted;
for (std::vector<Vec3d>::iterator itr = vertices.begin();
itr != vertices.end(); ++itr) {
converted.push_back(addVertex(*itr));
}
ly->_linestrips[correctedColorIndex(l, color)].push_back(converted);
}
void scene::addLineLoop(std::string l, unsigned short color, std::vector<Vec3d> vertices)
{
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
if (layer->getFrozen()) return;
sceneLayer* ly = findOrCreateSceneLayer(l);
std::vector<Vec3d> converted;
for (std::vector<Vec3d>::iterator itr = vertices.begin();
itr != vertices.end(); ++itr) {
converted.push_back(addVertex(*itr));
}
converted.push_back(addVertex(vertices.front()));
ly->_linestrips[correctedColorIndex(l, color)].push_back(converted);
}
void scene::addTriangles(std::string l, unsigned short color, std::vector<Vec3d> vertices, bool inverted)
{
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
if (layer->getFrozen()) return;
sceneLayer* ly = findOrCreateSceneLayer(l);
for (VList::iterator itr = vertices.begin();
itr != vertices.end(); ) {
VList::iterator a;
VList::iterator b;
VList::iterator c;
if (inverted) {
c = itr++;
b = itr++;
a = itr++;
} else {
a = itr++;
b = itr++;
c = itr++;
}
if (a != vertices.end() &&
b != vertices.end() &&
c != vertices.end()) {
Vec3d n = ((*b - *a) ^ (*c - *a));
n.normalize();
ly->_trinorms[correctedColorIndex(l, color)].push_back( n );
ly->_triangles[correctedColorIndex(l, color)].push_back(addVertex(*a));
ly->_triangles[correctedColorIndex(l, color)].push_back(addVertex(*b));
ly->_triangles[correctedColorIndex(l, color)].push_back(addVertex(*c));
}
}
}
void scene::addQuads(std::string l, unsigned short color, std::vector<Vec3d> vertices, bool inverted)
{
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
if (layer->getFrozen()) return;
sceneLayer* ly = findOrCreateSceneLayer(l);
for (VList::iterator itr = vertices.begin();
itr != vertices.end(); ) {
VList::iterator a = vertices.end();
VList::iterator b = vertices.end();
VList::iterator c = vertices.end();
VList::iterator d = vertices.end();
if (inverted) {
d = itr++;
if (itr != vertices.end())
c = itr++;
if (itr != vertices.end())
b = itr++;
if (itr != vertices.end())
a = itr++;
} else {
a = itr++;
if (itr != vertices.end())
b = itr++;
if (itr != vertices.end())
c = itr++;
if (itr != vertices.end())
d = itr++;
}
if (a != vertices.end() &&
b != vertices.end() &&
c != vertices.end()&&
d != vertices.end()) {
Vec3d n = ((*b - *a) ^ (*c - *a));
n.normalize();
short cindex = correctedColorIndex(l, color);
ly->_quadnorms[cindex].push_back( n );
MapVList mvl = ly->_quads;
VList vl = mvl[cindex];
vl.push_back(addVertex(*a));
vl.push_back(addVertex(*b));
vl.push_back(addVertex(*c));
vl.push_back(addVertex(*d));
mvl[cindex] = vl;
ly->_quads = mvl;
}
}
}
unsigned short
scene::correctedColorIndex(std::string l, unsigned short color)
{
if (color >= aci::MIN && color <= aci::MAX) {
return color;
} else if (!color || color == aci::BYLAYER) {
dxfLayer* layer = _layerTable->findOrCreateLayer(l);
unsigned short lcolor = layer->getColor();
if (lcolor >= aci::MIN && lcolor <= aci::MAX) {
return lcolor;
} else {
return aci::WHITE;
}
} else {
return aci::WHITE;
}
}

327
src/osgPlugins/dxf/scene.h Normal file
View File

@@ -0,0 +1,327 @@
/* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
* Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
*
* OpenSceneGraph is (C) 2004 Robert Osfield
*
* This library is provided as-is, without support of any kind.
*
* Read DXF docs or OSG docs for any related questions.
*
* You may contact the author if you have suggestions/corrections/enhancements.
*/
/** Simulate the scene with double precision before passing it back to osg.
this permits us to scale down offsets from 0,0,0 with a few matrixtransforms,
in case the objects are too far from that center.
*/
#ifndef DXF_SCENE
#define DXF_SCENE 1
#include <osg/Matrix>
#include <osg/Group>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Vec3d>
#include <osgUtil/SmoothingVisitor>
class dxfLayerTable;
class bounds {
public:
bounds() : _min(DBL_MAX, DBL_MAX, DBL_MAX), _max(-DBL_MAX, -DBL_MAX, -DBL_MAX) {}
inline void expandBy(osg::Vec3d v) {
if(v.x()<_min.x()) _min.x() = v.x();
if(v.x()>_max.x()) _max.x() = v.x();
if(v.y()<_min.y()) _min.y() = v.y();
if(v.y()>_max.y()) _max.y() = v.y();
if(v.z()<_min.z()) _min.z() = v.z();
if(v.z()>_max.z()) _max.z() = v.z();
}
inline void makeMinValid() {
// we count on _min to offset the whole scene
// so, we make sure its at 0,0,0 if
// bounds are not set (anyway, the scene should be empty,
// if we need to set any value of _min to 0).
if (_min.x() == DBL_MAX) _min.x() = 0;
if (_min.y() == DBL_MAX) _min.y() = 0;
if (_min.z() == DBL_MAX) _min.z() = 0;
}
osg::Vec3d _min;
osg::Vec3d _max;
};
static inline
osg::Geometry* createLnGeometry( osg::PrimitiveSet::Mode lineType, osg::Vec3Array* vertices, osg::Vec4 color)
{
osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(lineType, 0, vertices->size()));
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(color);
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
osg::Vec3Array *norms = new osg::Vec3Array;
norms->push_back(osg::Vec3(0,0,1));
geom->setNormalArray(norms);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
return geom;
}
static inline
osg::Geometry* createTriGeometry( osg::Vec3Array* vertices, osg::Vec3Array* normals, osg::Vec4 color)
{
osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices->size()));
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(color);
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
geom->setNormalArray(normals);
geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
return geom;
}
static inline
osg::Geometry* createQuadGeometry( osg::Vec3Array* vertices, osg::Vec3Array* normals, osg::Vec4 color)
{
osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(color);
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
geom->setNormalArray(normals);
geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
return geom;
}
static inline
osg::Geode* createModel(std::string name, osg::Geometry* geom)
{
osg::Geode* geom_geode = new osg::Geode;
geom_geode->addDrawable(geom);
geom_geode->setName(name);
return geom_geode;
}
static inline osg::Vec3d preMultd(const osg::Matrixd& m, const osg::Vec3d& v)
{
double d = 1.0f/(m(3,0)*v.x()+m(3,1)*v.y()+m(3,2)*v.z()+m(3,3)) ;
return osg::Vec3d( (m(0,0)*v.x() + m(1,0)*v.y() + m(2,0)*v.z() + m(3,0))*d,
(m(0,1)*v.x() + m(1,1)*v.y() + m(2,1)*v.z() + m(3,1))*d,
(m(0,2)*v.x() + m(1,2)*v.y() + m(2,2)*v.z() + m(3,2))*d) ;
}
static inline osg::Vec3d postMultd(const osg::Matrixd& m, const osg::Vec3d& v)
{
double d = 1.0f/(m(3,0)*v.x()+m(3,1)*v.y()+m(3,2)*v.z()+m(3,3)) ;
return osg::Vec3d( (m(0,0)*v.x() + m(0,1)*v.y() + m(0,2)*v.z() + m(0,3))*d,
(m(1,0)*v.x() + m(1,1)*v.y() + m(1,2)*v.z() + m(1,3))*d,
(m(2,0)*v.x() + m(2,1)*v.y() + m(2,2)*v.z() + m(2,3))*d) ;
}
typedef std::vector<osg::Vec3d> VList;
typedef std::map<unsigned short, VList> MapVList;
typedef std::vector<VList> VListList;
typedef std::map<unsigned short, VListList> MapVListList;
class sceneLayer : public osg::Referenced {
public:
sceneLayer(std::string name) : _name(name) {}
virtual ~sceneLayer() {}
void layer2osg(osg::Group* root, bounds &b)
{
osgLines(root, b);
osgTriangles(root, b);
osgQuads(root, b);
}
MapVListList _linestrips;
MapVList _lines;
MapVList _triangles;
MapVList _trinorms;
MapVList _quads;
MapVList _quadnorms;
protected:
std::string _name;
osg::Vec4 getColor(unsigned short color);
void osgLines(osg::Group* root, bounds &b)
{
for (MapVListList::iterator mitr = _linestrips.begin();
mitr != _linestrips.end(); ++mitr) {
for (VListList::iterator itr = mitr->second.begin();
itr != mitr->second.end(); ++itr) {
if (itr->size()) {
osg::Vec3Array *coords = new osg::Vec3Array;
for (VList::iterator vitr = itr->begin();
vitr != itr->end(); ++vitr) {
osg::Vec3 v(vitr->x() - b._min.x(), vitr->y() - b._min.y(), vitr->z() - b._min.z());
coords->push_back(v);
}
root->addChild(createModel(_name, createLnGeometry(osg::PrimitiveSet::LINE_STRIP, coords, getColor(mitr->first))));
}
}
}
for (MapVList::iterator mitr = _lines.begin();
mitr != _lines.end(); ++mitr) {
osg::Vec3Array *coords = new osg::Vec3Array;
for (VList::iterator itr = mitr->second.begin();
itr != mitr->second.end(); ++itr) {
osg::Vec3 v(itr->x() - b._min.x(), itr->y() - b._min.y(), itr->z() - b._min.z());
coords->push_back(v);
}
root->addChild(createModel(_name, createLnGeometry(osg::PrimitiveSet::LINES, coords, getColor(mitr->first))));
}
}
void osgTriangles(osg::Group* root, bounds &b)
{
if (_triangles.size()) {
for (MapVList::iterator mitr = _triangles.begin();
mitr != _triangles.end(); ++mitr) {
osg::Vec3Array *coords = new osg::Vec3Array;
for (VList::iterator itr = mitr->second.begin();
itr != mitr->second.end(); ++itr) {
osg::Vec3 v(itr->x() - b._min.x(), itr->y() - b._min.y(), itr->z() - b._min.z());
coords->push_back(v);
}
osg::Vec3Array *norms = new osg::Vec3Array;
VList normlist = _trinorms[mitr->first];
for (VList::iterator itr = normlist.begin();
itr != normlist.end(); ++itr) {
norms->push_back(osg::Vec3(itr->x(), itr->y(), itr->z()));
}
root->addChild(createModel(_name, createTriGeometry(coords, norms, getColor(mitr->first))));
}
}
}
void osgQuads(osg::Group* root, bounds &b)
{
if (_quads.size()) {
for (MapVList::iterator mitr = _quads.begin();
mitr != _quads.end(); ++mitr) {
osg::Vec3Array *coords = new osg::Vec3Array;
for (VList::iterator itr = mitr->second.begin();
itr != mitr->second.end(); ++itr) {
osg::Vec3 v(itr->x() - b._min.x(), itr->y() - b._min.y(), itr->z() - b._min.z());
coords->push_back(v);
}
osg::Vec3Array *norms = new osg::Vec3Array;
VList normlist = _quadnorms[mitr->first];
for (VList::iterator itr = normlist.begin();
itr != normlist.end(); ++itr) {
norms->push_back(osg::Vec3(itr->x(), itr->y(), itr->z()));
}
root->addChild(createModel(_name, createQuadGeometry(coords, norms, getColor(mitr->first))));
}
}
}
};
class scene : public osg::Referenced {
public:
scene(dxfLayerTable* lt = NULL);
virtual ~scene() {}
void setLayerTable(dxfLayerTable* lt);
void pushMatrix(osg::Matrixd m, bool protect = false)
{
_mStack.push_back(_m);
if (protect) // equivalent to setMatrix
_m = m;
else
_m = _m * m;
}
void popMatrix()
{
_mStack.pop_back();
if (_mStack.size())
_m = _mStack.back();
else
_m.makeIdentity();
}
void ocs(osg::Matrixd r)
{
_r = r;
}
void blockOffset(osg::Vec3d t)
{
_t = t;
}
void ocs_clear()
{
_r.makeIdentity();
}
osg::Matrixd& backMatrix() { if (_mStack.size()) return _mStack.back(); else return _m; }
osg::Vec3d addVertex(osg::Vec3d v);
osg::Vec3d addNormal(osg::Vec3d v);
sceneLayer* findOrCreateSceneLayer(std::string l)
{
sceneLayer* ly = _layers[l].get();
if (!ly) {
ly = new sceneLayer(l);
_layers[l] = ly;
}
return ly;
}
unsigned short correctedColorIndex(std::string l, unsigned short color);
void addLine(std::string l, unsigned short color, osg::Vec3d s, osg::Vec3d e);
void addLineStrip(std::string l, unsigned short color, std::vector<osg::Vec3d> vertices);
void addLineLoop(std::string l, unsigned short color, std::vector<osg::Vec3d> vertices);
void addTriangles(std::string l, unsigned short color, std::vector<osg::Vec3d> vertices, bool inverted=false);
void addQuads(std::string l, unsigned short color, std::vector<osg::Vec3d> vertices, bool inverted=false);
osg::Group* scene2osg()
{
osg::Group* root = NULL;
osg::Group* child = NULL;
_b.makeMinValid();
osg::Vec3 v = osg::Vec3(_b._min.x(), _b._min.y(), _b._min.z());
double x = _b._min.x() - (double)v.x();
double y = _b._min.y() - (double)v.y();
double z = _b._min.z() - (double)v.z();
osg::Matrix m = osg::Matrix::translate(v);
root = new osg::MatrixTransform(m);
if (x || y || z) {
m = osg::Matrix::translate(x,y,z);
child = new osg::MatrixTransform(m);
root->addChild(child);
} else {
child = root;
}
// root = mt;
for (std::map<std::string, osg::ref_ptr<sceneLayer> >::iterator litr = _layers.begin();
litr != _layers.end(); ++litr) {
sceneLayer* ly = (*litr).second.get();
if (!ly) continue;
osg::Group* lg = new osg::Group;
lg->setName((*litr).first);
child->addChild(lg);
ly->layer2osg(lg, _b);
}
return root;
}
protected:
osg::Matrixd _m;
osg::Matrixd _r;
osg::Vec3d _t;
bounds _b;
std::map<std::string, osg::ref_ptr<sceneLayer> > _layers;
std::vector<osg::Matrixd> _mStack;
dxfLayerTable* _layerTable;
};
#endif

View File

@@ -2,7 +2,8 @@
#pragma warning( disable : 4786 )
#endif
#include "osg/ClipPlane"
#include <osg/ClipPlane>
#include <osg/io_utils>
#include "osgDB/Registry"
#include "osgDB/Input"

View File

@@ -6,6 +6,7 @@
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/io_utils>
#include <osgDB/Registry>
#include <osgDB/Input>