This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
694 lines
20 KiB
C++
694 lines
20 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: dxfrenderer.cpp
|
|
// Purpose: DXF reader and renderer
|
|
// Author: Sandro Sigala
|
|
// Modified by:
|
|
// Created: 2005-11-10
|
|
// Copyright: (c) Sandro Sigala
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx/wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif
|
|
|
|
#include "wx/wfstream.h"
|
|
#include "wx/txtstrm.h"
|
|
|
|
#if !wxUSE_GLCANVAS
|
|
#error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
|
#endif
|
|
|
|
#ifdef __DARWIN__
|
|
#include <OpenGL/glu.h>
|
|
#else
|
|
#include <GL/glu.h>
|
|
#endif
|
|
|
|
#include <sstream>
|
|
|
|
#include "dxfrenderer.h"
|
|
|
|
#include "wx/listimpl.cpp"
|
|
WX_DEFINE_LIST(DXFEntityList)
|
|
WX_DEFINE_LIST(DXFLayerList)
|
|
|
|
// Conversion table from AutoCAD ACI colours to RGB values
|
|
static const struct { unsigned char r, g, b; } aci_to_rgb[256] = {
|
|
/* 0 */ {255, 255, 255},
|
|
/* 1 */ {255, 0, 0},
|
|
/* 2 */ {255, 255, 0},
|
|
/* 3 */ { 0, 255, 0},
|
|
/* 4 */ { 0, 255, 255},
|
|
/* 5 */ { 0, 0, 255},
|
|
/* 6 */ {255, 0, 255},
|
|
/* 7 */ {255, 255, 255},
|
|
/* 8 */ {128, 128, 128},
|
|
/* 9 */ {192, 192, 192},
|
|
/* 10 */ {255, 0, 0},
|
|
/* 11 */ {255, 127, 127},
|
|
/* 12 */ {204, 0, 0},
|
|
/* 13 */ {204, 102, 102},
|
|
/* 14 */ {153, 0, 0},
|
|
/* 15 */ {153, 76, 76},
|
|
/* 16 */ {127, 0, 0},
|
|
/* 17 */ {127, 63, 63},
|
|
/* 18 */ { 76, 0, 0},
|
|
/* 19 */ { 76, 38, 38},
|
|
/* 20 */ {255, 63, 0},
|
|
/* 21 */ {255, 159, 127},
|
|
/* 22 */ {204, 51, 0},
|
|
/* 23 */ {204, 127, 102},
|
|
/* 24 */ {153, 38, 0},
|
|
/* 25 */ {153, 95, 76},
|
|
/* 26 */ {127, 31, 0},
|
|
/* 27 */ {127, 79, 63},
|
|
/* 28 */ { 76, 19, 0},
|
|
/* 29 */ { 76, 47, 38},
|
|
/* 30 */ {255, 127, 0},
|
|
/* 31 */ {255, 191, 127},
|
|
/* 32 */ {204, 102, 0},
|
|
/* 33 */ {204, 153, 102},
|
|
/* 34 */ {153, 76, 0},
|
|
/* 35 */ {153, 114, 76},
|
|
/* 36 */ {127, 63, 0},
|
|
/* 37 */ {127, 95, 63},
|
|
/* 38 */ { 76, 38, 0},
|
|
/* 39 */ { 76, 57, 38},
|
|
/* 40 */ {255, 191, 0},
|
|
/* 41 */ {255, 223, 127},
|
|
/* 42 */ {204, 153, 0},
|
|
/* 43 */ {204, 178, 102},
|
|
/* 44 */ {153, 114, 0},
|
|
/* 45 */ {153, 133, 76},
|
|
/* 46 */ {127, 95, 0},
|
|
/* 47 */ {127, 111, 63},
|
|
/* 48 */ { 76, 57, 0},
|
|
/* 49 */ { 76, 66, 38},
|
|
/* 50 */ {255, 255, 0},
|
|
/* 51 */ {255, 255, 127},
|
|
/* 52 */ {204, 204, 0},
|
|
/* 53 */ {204, 204, 102},
|
|
/* 54 */ {153, 153, 0},
|
|
/* 55 */ {153, 153, 76},
|
|
/* 56 */ {127, 127, 0},
|
|
/* 57 */ {127, 127, 63},
|
|
/* 58 */ { 76, 76, 0},
|
|
/* 59 */ { 76, 76, 38},
|
|
/* 60 */ {191, 255, 0},
|
|
/* 61 */ {223, 255, 127},
|
|
/* 62 */ {153, 204, 0},
|
|
/* 63 */ {178, 204, 102},
|
|
/* 64 */ {114, 153, 0},
|
|
/* 65 */ {133, 153, 76},
|
|
/* 66 */ { 95, 127, 0},
|
|
/* 67 */ {111, 127, 63},
|
|
/* 68 */ { 57, 76, 0},
|
|
/* 69 */ { 66, 76, 38},
|
|
/* 70 */ {127, 255, 0},
|
|
/* 71 */ {191, 255, 127},
|
|
/* 72 */ {102, 204, 0},
|
|
/* 73 */ {153, 204, 102},
|
|
/* 74 */ { 76, 153, 0},
|
|
/* 75 */ {114, 153, 76},
|
|
/* 76 */ { 63, 127, 0},
|
|
/* 77 */ { 95, 127, 63},
|
|
/* 78 */ { 38, 76, 0},
|
|
/* 79 */ { 57, 76, 38},
|
|
/* 80 */ { 63, 255, 0},
|
|
/* 81 */ {159, 255, 127},
|
|
/* 82 */ { 51, 204, 0},
|
|
/* 83 */ {127, 204, 102},
|
|
/* 84 */ { 38, 153, 0},
|
|
/* 85 */ { 95, 153, 76},
|
|
/* 86 */ { 31, 127, 0},
|
|
/* 87 */ { 79, 127, 63},
|
|
/* 88 */ { 19, 76, 0},
|
|
/* 89 */ { 47, 76, 38},
|
|
/* 90 */ { 0, 255, 0},
|
|
/* 91 */ {127, 255, 127},
|
|
/* 92 */ { 0, 204, 0},
|
|
/* 93 */ {102, 204, 102},
|
|
/* 94 */ { 0, 153, 0},
|
|
/* 95 */ { 76, 153, 76},
|
|
/* 96 */ { 0, 127, 0},
|
|
/* 97 */ { 63, 127, 63},
|
|
/* 98 */ { 0, 76, 0},
|
|
/* 99 */ { 38, 76, 38},
|
|
/* 100 */ { 0, 255, 63},
|
|
/* 101 */ {127, 255, 159},
|
|
/* 102 */ { 0, 204, 51},
|
|
/* 103 */ {102, 204, 127},
|
|
/* 104 */ { 0, 153, 38},
|
|
/* 105 */ { 76, 153, 95},
|
|
/* 106 */ { 0, 127, 31},
|
|
/* 107 */ { 63, 127, 79},
|
|
/* 108 */ { 0, 76, 19},
|
|
/* 109 */ { 38, 76, 47},
|
|
/* 110 */ { 0, 255, 127},
|
|
/* 111 */ {127, 255, 191},
|
|
/* 112 */ { 0, 204, 102},
|
|
/* 113 */ {102, 204, 153},
|
|
/* 114 */ { 0, 153, 76},
|
|
/* 115 */ { 76, 153, 114},
|
|
/* 116 */ { 0, 127, 63},
|
|
/* 117 */ { 63, 127, 95},
|
|
/* 118 */ { 0, 76, 38},
|
|
/* 119 */ { 38, 76, 57},
|
|
/* 120 */ { 0, 255, 191},
|
|
/* 121 */ {127, 255, 223},
|
|
/* 122 */ { 0, 204, 153},
|
|
/* 123 */ {102, 204, 178},
|
|
/* 124 */ { 0, 153, 114},
|
|
/* 125 */ { 76, 153, 133},
|
|
/* 126 */ { 0, 127, 95},
|
|
/* 127 */ { 63, 127, 111},
|
|
/* 128 */ { 0, 76, 57},
|
|
/* 129 */ { 38, 76, 66},
|
|
/* 130 */ { 0, 255, 255},
|
|
/* 131 */ {127, 255, 255},
|
|
/* 132 */ { 0, 204, 204},
|
|
/* 133 */ {102, 204, 204},
|
|
/* 134 */ { 0, 153, 153},
|
|
/* 135 */ { 76, 153, 153},
|
|
/* 136 */ { 0, 127, 127},
|
|
/* 137 */ { 63, 127, 127},
|
|
/* 138 */ { 0, 76, 76},
|
|
/* 139 */ { 38, 76, 76},
|
|
/* 140 */ { 0, 191, 255},
|
|
/* 141 */ {127, 223, 255},
|
|
/* 142 */ { 0, 153, 204},
|
|
/* 143 */ {102, 178, 204},
|
|
/* 144 */ { 0, 114, 153},
|
|
/* 145 */ { 76, 133, 153},
|
|
/* 146 */ { 0, 95, 127},
|
|
/* 147 */ { 63, 111, 127},
|
|
/* 148 */ { 0, 57, 76},
|
|
/* 149 */ { 38, 66, 76},
|
|
/* 150 */ { 0, 127, 255},
|
|
/* 151 */ {127, 191, 255},
|
|
/* 152 */ { 0, 102, 204},
|
|
/* 153 */ {102, 153, 204},
|
|
/* 154 */ { 0, 76, 153},
|
|
/* 155 */ { 76, 114, 153},
|
|
/* 156 */ { 0, 63, 127},
|
|
/* 157 */ { 63, 95, 127},
|
|
/* 158 */ { 0, 38, 76},
|
|
/* 159 */ { 38, 57, 76},
|
|
/* 160 */ { 0, 63, 255},
|
|
/* 161 */ {127, 159, 255},
|
|
/* 162 */ { 0, 51, 204},
|
|
/* 163 */ {102, 127, 204},
|
|
/* 164 */ { 0, 38, 153},
|
|
/* 165 */ { 76, 95, 153},
|
|
/* 166 */ { 0, 31, 127},
|
|
/* 167 */ { 63, 79, 127},
|
|
/* 168 */ { 0, 19, 76},
|
|
/* 169 */ { 38, 47, 76},
|
|
/* 170 */ { 0, 0, 255},
|
|
/* 171 */ {127, 127, 255},
|
|
/* 172 */ { 0, 0, 204},
|
|
/* 173 */ {102, 102, 204},
|
|
/* 174 */ { 0, 0, 153},
|
|
/* 175 */ { 76, 76, 153},
|
|
/* 176 */ { 0, 0, 127},
|
|
/* 177 */ { 63, 63, 127},
|
|
/* 178 */ { 0, 0, 76},
|
|
/* 179 */ { 38, 38, 76},
|
|
/* 180 */ { 63, 0, 255},
|
|
/* 181 */ {159, 127, 255},
|
|
/* 182 */ { 51, 0, 204},
|
|
/* 183 */ {127, 102, 204},
|
|
/* 184 */ { 38, 0, 153},
|
|
/* 185 */ { 95, 76, 153},
|
|
/* 186 */ { 31, 0, 127},
|
|
/* 187 */ { 79, 63, 127},
|
|
/* 188 */ { 19, 0, 76},
|
|
/* 189 */ { 47, 38, 76},
|
|
/* 190 */ {127, 0, 255},
|
|
/* 191 */ {191, 127, 255},
|
|
/* 192 */ {102, 0, 204},
|
|
/* 193 */ {153, 102, 204},
|
|
/* 194 */ { 76, 0, 153},
|
|
/* 195 */ {114, 76, 153},
|
|
/* 196 */ { 63, 0, 127},
|
|
/* 197 */ { 95, 63, 127},
|
|
/* 198 */ { 38, 0, 76},
|
|
/* 199 */ { 57, 38, 76},
|
|
/* 200 */ {191, 0, 255},
|
|
/* 201 */ {223, 127, 255},
|
|
/* 202 */ {153, 0, 204},
|
|
/* 203 */ {178, 102, 204},
|
|
/* 204 */ {114, 0, 153},
|
|
/* 205 */ {133, 76, 153},
|
|
/* 206 */ { 95, 0, 127},
|
|
/* 207 */ {111, 63, 127},
|
|
/* 208 */ { 57, 0, 76},
|
|
/* 209 */ { 66, 38, 76},
|
|
/* 210 */ {255, 0, 255},
|
|
/* 211 */ {255, 127, 255},
|
|
/* 212 */ {204, 0, 204},
|
|
/* 213 */ {204, 102, 204},
|
|
/* 214 */ {153, 0, 153},
|
|
/* 215 */ {153, 76, 153},
|
|
/* 216 */ {127, 0, 127},
|
|
/* 217 */ {127, 63, 127},
|
|
/* 218 */ { 76, 0, 76},
|
|
/* 219 */ { 76, 38, 76},
|
|
/* 220 */ {255, 0, 191},
|
|
/* 221 */ {255, 127, 223},
|
|
/* 222 */ {204, 0, 153},
|
|
/* 223 */ {204, 102, 178},
|
|
/* 224 */ {153, 0, 114},
|
|
/* 225 */ {153, 76, 133},
|
|
/* 226 */ {127, 0, 95},
|
|
/* 227 */ {127, 63, 111},
|
|
/* 228 */ { 76, 0, 57},
|
|
/* 229 */ { 76, 38, 66},
|
|
/* 230 */ {255, 0, 127},
|
|
/* 231 */ {255, 127, 191},
|
|
/* 232 */ {204, 0, 102},
|
|
/* 233 */ {204, 102, 153},
|
|
/* 234 */ {153, 0, 76},
|
|
/* 235 */ {153, 76, 114},
|
|
/* 236 */ {127, 0, 63},
|
|
/* 237 */ {127, 63, 95},
|
|
/* 238 */ { 76, 0, 38},
|
|
/* 239 */ { 76, 38, 57},
|
|
/* 240 */ {255, 0, 63},
|
|
/* 241 */ {255, 127, 159},
|
|
/* 242 */ {204, 0, 51},
|
|
/* 243 */ {204, 102, 127},
|
|
/* 244 */ {153, 0, 38},
|
|
/* 245 */ {153, 76, 95},
|
|
/* 246 */ {127, 0, 31},
|
|
/* 247 */ {127, 63, 79},
|
|
/* 248 */ { 76, 0, 19},
|
|
/* 249 */ { 76, 38, 47},
|
|
/* 250 */ { 51, 51, 51},
|
|
/* 251 */ { 91, 91, 91},
|
|
/* 252 */ {132, 132, 132},
|
|
/* 253 */ {173, 173, 173},
|
|
/* 254 */ {214, 214, 214},
|
|
/* 255 */ {255, 255, 255}
|
|
};
|
|
|
|
inline DXFVector Cross(const DXFVector& v1, const DXFVector& v2)
|
|
{
|
|
return DXFVector(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
|
|
}
|
|
|
|
void DXFFace::CalculateNormal()
|
|
{
|
|
DXFVector v01, v02;
|
|
v01.x = v0.x - v1.x;
|
|
v01.y = v0.y - v1.y;
|
|
v01.z = v0.z - v1.z;
|
|
v02.x = v0.x - v2.x;
|
|
v02.y = v0.y - v2.y;
|
|
v02.z = v0.z - v2.z;
|
|
n = Cross(v01, v02);
|
|
float mod = sqrt(n.x*n.x + n.y*n.y + n.z*n.z);
|
|
n.x /= mod;
|
|
n.y /= mod;
|
|
n.z /= mod;
|
|
}
|
|
|
|
// convert an AutoCAD ACI colour to wxWidgets RGB colour
|
|
inline wxColour ACIColourToRGB(int col)
|
|
{
|
|
wxASSERT(col >= 0 && col <= 255);
|
|
return wxColour(aci_to_rgb[col].r, aci_to_rgb[col].g, aci_to_rgb[col].b);
|
|
}
|
|
|
|
// DXFReader constructor
|
|
DXFRenderer::DXFRenderer()
|
|
{
|
|
m_loaded = false;
|
|
}
|
|
|
|
// DXFReader destructor
|
|
DXFRenderer::~DXFRenderer()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
// deallocate all the dynamic data
|
|
void DXFRenderer::Clear()
|
|
{
|
|
m_loaded = false;
|
|
{
|
|
for (DXFLayerList::compatibility_iterator node = m_layers.GetFirst(); node; node = node->GetNext())
|
|
{
|
|
DXFLayer *current = node->GetData();
|
|
delete current;
|
|
}
|
|
}
|
|
m_layers.Clear();
|
|
{
|
|
for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
|
|
{
|
|
DXFEntity *current = node->GetData();
|
|
delete current;
|
|
}
|
|
m_entities.Clear();
|
|
}
|
|
}
|
|
|
|
int DXFRenderer::GetLayerColour(const wxString& layer) const
|
|
{
|
|
for (DXFLayerList::compatibility_iterator node = m_layers.GetFirst(); node; node = node->GetNext())
|
|
{
|
|
DXFLayer *current = node->GetData();
|
|
if (current->name == layer)
|
|
return current->colour;
|
|
}
|
|
return 7; // white
|
|
}
|
|
|
|
// read two sequential lines
|
|
inline void GetLines(wxTextInputStream& text, wxString& line1, wxString& line2)
|
|
{
|
|
line1 = text.ReadLine().Trim().Trim(false);
|
|
line2 = text.ReadLine().Trim().Trim(false);
|
|
}
|
|
|
|
// parse header section: just skip everything
|
|
bool DXFRenderer::ParseHeader(wxInputStream& stream)
|
|
{
|
|
wxTextInputStream text(stream);
|
|
wxString line1, line2;
|
|
while (stream.CanRead())
|
|
{
|
|
GetLines(text, line1, line2);
|
|
if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// parse tables section: save layers name and colour
|
|
bool DXFRenderer::ParseTables(wxInputStream& stream)
|
|
{
|
|
wxTextInputStream text(stream);
|
|
wxString line1, line2;
|
|
bool inlayer=false;
|
|
DXFLayer layer;
|
|
while (stream.CanRead())
|
|
{
|
|
GetLines(text, line1, line2);
|
|
if (line1 == wxT("0") && inlayer)
|
|
{
|
|
// flush layer
|
|
if (!layer.name.IsEmpty() && layer.colour != -1)
|
|
{
|
|
DXFLayer *p = new DXFLayer;
|
|
p->name = layer.name;
|
|
p->colour = layer.colour;
|
|
m_layers.Append(p);
|
|
}
|
|
layer = DXFLayer();
|
|
inlayer = false;
|
|
}
|
|
if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
|
|
return true;
|
|
else if (line1 == wxT("0") && line2 == wxT("LAYER"))
|
|
inlayer = true;
|
|
else if (inlayer)
|
|
{
|
|
if (line1 == wxT("2")) // layer name
|
|
layer.name = line2;
|
|
else if (line1 == wxT("62")) // ACI colour
|
|
{
|
|
long l;
|
|
line2.ToLong(&l);
|
|
layer.colour = l;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// This method is used instead of numStr.ToDouble(d) because the latter
|
|
// (wxString::ToDouble()) takes the systems proper locale into account,
|
|
// whereas the implementation below works with the default locale.
|
|
// (Converting numbers that are formatted in the default locale can fail
|
|
// with system locales that use e.g. the comma as the decimal separator.)
|
|
static double ToDouble(const wxString& numStr)
|
|
{
|
|
double d;
|
|
std::string numStr_(numStr.c_str());
|
|
std::istringstream iss(numStr_);
|
|
|
|
iss >> d;
|
|
|
|
return d;
|
|
}
|
|
|
|
// parse entities section: save 3DFACE and LINE entities
|
|
bool DXFRenderer::ParseEntities(wxInputStream& stream)
|
|
{
|
|
wxTextInputStream text(stream);
|
|
wxString line1, line2;
|
|
int state = 0; // 0: none, 1: 3DFACE, 2: LINE
|
|
DXFVector v[4];
|
|
int colour = -1;
|
|
wxString layer;
|
|
while (stream.CanRead())
|
|
{
|
|
GetLines(text, line1, line2);
|
|
if (line1 == wxT("0") && state > 0)
|
|
{
|
|
// flush entity
|
|
if (state == 1) // 3DFACE
|
|
{
|
|
DXFFace *p = new DXFFace;
|
|
p->v0 = v[0];
|
|
p->v1 = v[1];
|
|
p->v2 = v[2];
|
|
p->v3 = v[3];
|
|
p->CalculateNormal();
|
|
if (colour != -1)
|
|
p->colour = colour;
|
|
else
|
|
p->colour = GetLayerColour(layer);
|
|
m_entities.Append(p);
|
|
colour = -1; layer = wxEmptyString;
|
|
v[0] = v[1] = v[2] = v[3] = DXFVector();
|
|
state = 0;
|
|
}
|
|
else if (state == 2) // LINE
|
|
{
|
|
DXFLine *p = new DXFLine;
|
|
p->v0 = v[0];
|
|
p->v1 = v[1];
|
|
if (colour != -1)
|
|
p->colour = colour;
|
|
else
|
|
p->colour = GetLayerColour(layer);
|
|
m_entities.Append(p);
|
|
colour = -1; layer = wxEmptyString;
|
|
v[0] = v[1] = v[2] = v[3] = DXFVector();
|
|
state = 0;
|
|
}
|
|
}
|
|
if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
|
|
return true;
|
|
else if (line1 == wxT("0") && line2 == wxT("3DFACE"))
|
|
state = 1;
|
|
else if (line1 == wxT("0") && line2 == wxT("LINE"))
|
|
state = 2;
|
|
else if (state > 0)
|
|
{
|
|
const double d=ToDouble(line2);
|
|
|
|
if (line1 == wxT("10"))
|
|
v[0].x = d;
|
|
else if (line1 == wxT("20"))
|
|
v[0].y = d;
|
|
else if (line1 == wxT("30"))
|
|
v[0].z = d;
|
|
else if (line1 == wxT("11"))
|
|
v[1].x = d;
|
|
else if (line1 == wxT("21"))
|
|
v[1].y = d;
|
|
else if (line1 == wxT("31"))
|
|
v[1].z = d;
|
|
else if (line1 == wxT("12"))
|
|
v[2].x = d;
|
|
else if (line1 == wxT("22"))
|
|
v[2].y = d;
|
|
else if (line1 == wxT("32"))
|
|
v[2].z = d;
|
|
else if (line1 == wxT("13"))
|
|
v[3].x = d;
|
|
else if (line1 == wxT("23"))
|
|
v[3].y = d;
|
|
else if (line1 == wxT("33"))
|
|
v[3].z = d;
|
|
else if (line1 == wxT("8")) // layer
|
|
layer = line2;
|
|
else if (line1 == wxT("62")) // colour
|
|
{
|
|
long l;
|
|
line2.ToLong(&l);
|
|
colour = l;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// parse and load a DXF file
|
|
// currently pretty limited, but knows enought do handle 3DFACEs and LINEs
|
|
bool DXFRenderer::Load(wxInputStream& stream)
|
|
{
|
|
Clear();
|
|
wxTextInputStream text(stream);
|
|
|
|
wxString line1, line2;
|
|
while (stream.CanRead())
|
|
{
|
|
GetLines(text, line1, line2);
|
|
if (line1 == wxT("999")) // comment
|
|
continue;
|
|
else if (line1 == wxT("0") && line2 == wxT("SECTION"))
|
|
{
|
|
GetLines(text, line1, line2);
|
|
if (line1 == wxT("2"))
|
|
{
|
|
if (line2 == wxT("HEADER"))
|
|
{
|
|
if (!ParseHeader(stream))
|
|
return false;
|
|
}
|
|
else if (line2 == wxT("TABLES"))
|
|
{
|
|
if (!ParseTables(stream))
|
|
return false;
|
|
}
|
|
else if (line2 == wxT("ENTITIES"))
|
|
{
|
|
if (!ParseEntities(stream))
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NormalizeEntities();
|
|
m_loaded = true;
|
|
return true;
|
|
}
|
|
|
|
inline float mymin(float x, float y) { return x < y ? x : y; }
|
|
inline float mymax(float x, float y) { return x > y ? x : y; }
|
|
|
|
// Scale object boundings to [-5,5]
|
|
void DXFRenderer::NormalizeEntities()
|
|
{
|
|
// calculate current min and max boundings of object
|
|
DXFVector minv(10e20f, 10e20f, 10e20f);
|
|
DXFVector maxv(-10e20f, -10e20f, -10e20f);
|
|
for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
|
|
{
|
|
DXFEntity *p = node->GetData();
|
|
if (p->type == DXFEntity::Line)
|
|
{
|
|
DXFLine *line = (DXFLine *)p;
|
|
const DXFVector *v[2] = { &line->v0, &line->v1 };
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
minv.x = mymin(v[i]->x, minv.x);
|
|
minv.y = mymin(v[i]->y, minv.y);
|
|
minv.z = mymin(v[i]->z, minv.z);
|
|
maxv.x = mymax(v[i]->x, maxv.x);
|
|
maxv.y = mymax(v[i]->y, maxv.y);
|
|
maxv.z = mymax(v[i]->z, maxv.z);
|
|
}
|
|
} else if (p->type == DXFEntity::Face)
|
|
{
|
|
DXFFace *face = (DXFFace *)p;
|
|
const DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
minv.x = mymin(v[i]->x, minv.x);
|
|
minv.y = mymin(v[i]->y, minv.y);
|
|
minv.z = mymin(v[i]->z, minv.z);
|
|
maxv.x = mymax(v[i]->x, maxv.x);
|
|
maxv.y = mymax(v[i]->y, maxv.y);
|
|
maxv.z = mymax(v[i]->z, maxv.z);
|
|
}
|
|
}
|
|
}
|
|
|
|
// rescale object down to [-5,5]
|
|
DXFVector span(maxv.x - minv.x, maxv.y - minv.y, maxv.z - minv.z);
|
|
float factor = mymin(mymin(10.0f / span.x, 10.0f / span.y), 10.0f / span.z);
|
|
for (DXFEntityList::compatibility_iterator node2 = m_entities.GetFirst(); node2; node2 = node2->GetNext())
|
|
{
|
|
DXFEntity *p = node2->GetData();
|
|
if (p->type == DXFEntity::Line)
|
|
{
|
|
DXFLine *line = (DXFLine *)p;
|
|
DXFVector *v[2] = { &line->v0, &line->v1 };
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
|
|
v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
|
|
v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
|
|
}
|
|
} else if (p->type == DXFEntity::Face)
|
|
{
|
|
DXFFace *face = (DXFFace *)p;
|
|
DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
|
|
v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
|
|
v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// OpenGL renderer for DXF entities
|
|
void DXFRenderer::Render() const
|
|
{
|
|
if (!m_loaded)
|
|
return;
|
|
|
|
for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
|
|
{
|
|
DXFEntity *p = node->GetData();
|
|
wxColour c = ACIColourToRGB(p->colour);
|
|
if (p->type == DXFEntity::Line)
|
|
{
|
|
DXFLine *line = (DXFLine *)p;
|
|
glBegin(GL_LINES);
|
|
glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
|
|
glVertex3f(line->v0.x, line->v0.y, line->v0.z);
|
|
glVertex3f(line->v1.x, line->v1.y, line->v1.z);
|
|
glEnd();
|
|
}
|
|
else if (p->type == DXFEntity::Face)
|
|
{
|
|
DXFFace *face = (DXFFace *)p;
|
|
glBegin(GL_TRIANGLES);
|
|
glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
|
|
glNormal3f(face->n.x, face->n.y, face->n.z);
|
|
glVertex3f(face->v0.x, face->v0.y, face->v0.z);
|
|
glVertex3f(face->v1.x, face->v1.y, face->v1.z);
|
|
glVertex3f(face->v2.x, face->v2.y, face->v2.z);
|
|
glEnd();
|
|
}
|
|
}
|
|
}
|