Sophie

Sophie

distrib > * > 2010.0 > * > by-pkgid > 4d4bff3fc831b905f4306148550d3c39 > files > 2231

lib64wxgtku2.8-devel-2.8.10-3mdv2010.0.x86_64.rpm

/////////////////////////////////////////////////////////////////////////////
// Name:        dxfrenderer.cpp
// Purpose:     DXF reader and renderer
// Author:      Sandro Sigala
// Modified by:
// Created:     2005-11-10
// RCS-ID:      $Id: dxfrenderer.cpp 43272 2006-11-10 15:16:02Z VZ $
// 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 "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;
}

// 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)
        {
            double d;
            line2.ToDouble(&d);
            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();
        }
    }
}