DXF Viewer:计算GDI +的挤出矩阵

时间:2016-08-15 13:06:20

标签: c# matrix gdi+ dxf

我目前正致力于DXF图纸的查看器。我已经可以读取文件(至少是最常见的表和实体)并绘制它们。但是我有一个很难理解/实施的大问题。

大多数实体都有一个挤压矢量(如果我理解正确的话,我必须绘制表面的法线)

我的问题是如何计算我必须在OnPaint方法中应用于Graphics对象的矩阵。

这是一个带有非默认挤压的LINE权利的示例:

  0
LINE                   // Start of Entity
  5
A08E5                  // Handle
330
70                     // Soft-Pointer ID
100
AcDbEntity             // Start of common entity data
  8
Level 19               // Layername
  6
Continuous             // Line type name
 62
     4                 // Color number (ARGB = 255, 0, 255, 255)
370
    30                 // Line weight
100
AcDbLine               // Start of specific line entity data
 10
208157.9494861194      // Start point X coordinate
 20
206799.7837580488      // Start point Y coordinate
 30
0.0                    // Start point Z coordinate
 11
203237.9494861194      // End point X coordinate
 21
206799.7837580488      // End point Y coordinate
 31
0.0                    // End point Z coordinate
210
0.0                    // Extrusion direction X  (0==Default)
220
0.0                    // Extrusion direction Y  (0==Default)
230
-1.0                   // Extrusion direction Z  (1==Default)

我已经知道给定示例中的Extrusion将起始和结束X值乘以-1,但由于挤出矢量可以指向任何方向,我需要一个适当的转换矩阵。

感谢任何帮助。

托马斯

1 个答案:

答案 0 :(得分:1)

我从未真正理解 matrices ,多年前我得到了以下帮助。

请注意,此代码为C++而不是C#,但可以直接将其移至C#而不会有太多麻烦。

您可能会发现可以根据需要提取部分内容。它旨在将对象坐标系统转换为世界坐标系统:

标题

// Matrix.h: interface for the CMatrix class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MATRIX_H__75B83784_0447_42D4_A1C1_7D86BA4F1ADE__INCLUDED_)
#define AFX_MATRIX_H__75B83784_0447_42D4_A1C1_7D86BA4F1ADE__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#define AXIS double
#define VECTOR double
#define ZERO 0.0
#define ONE 1.0
#define ARBBOUND 0.015625

enum { X, Y, Z, W};
typedef double MATRIX[4][4];

class CMatrix  
{
public:
    void TransVectorToWCS(VECTOR *newpt0);
    void TransVectorToOCS(VECTOR *newpt0);
    void SetMatrices(AXIS *N);
    void PrintVectorUnitLength(AXIS *Av);
    CMatrix();
    virtual ~CMatrix();

private:
    void SetOCSMatrix(AXIS *N);
    void GetArbitraryAxis(AXIS *N, AXIS *Ax, AXIS *Ay);
    void InvertMatrix(void);
    void ScaleVectorToUnitLength(AXIS *Av);
    void CrossProduct(AXIS *Av, AXIS *V1, AXIS *V2);
    double Squared(double val);
    MATRIX m_mWCS;
    MATRIX m_mOCS;
};

#endif // !defined(AFX_MATRIX_H__75B83784_0447_42D4_A1C1_7D86BA4F1ADE__INCLUDED_)

来源

// Matrix.cpp: implementation of the CMatrix class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DxfRen.h"
#include "Matrix.h"
#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMatrix::CMatrix()
{

}

CMatrix::~CMatrix()
{

}

void CMatrix::SetMatrices(AXIS * N)
{
    SetOCSMatrix(N);
    InvertMatrix();
}

/*
** get the ocs 4x4 matrix
**
** MATRIX: Ax[X] Ax[Y] Ax[Z] 0
**         Ay[X] Ay[Y] Ay[Z] 0
**         Az[X] Az[Y] Az[Z] 0
**         0     0     0     1
*/
void CMatrix::SetOCSMatrix(AXIS * N)
{
    AXIS Ax[3], Ay[3];

    GetArbitraryAxis(N, Ax, Ay);

    /* fill in matrix */
    m_mOCS[X][X] = Ax[X]; m_mOCS[X][Y] = Ax[Y]; m_mOCS[X][Z] = Ax[Z];
    m_mOCS[Y][X] = Ay[X]; m_mOCS[Y][Y] = Ay[Y]; m_mOCS[Y][Z] = Ay[Z];
    m_mOCS[Z][X] = N[X]; m_mOCS[Z][Y] = N[Y]; m_mOCS[Z][Z] = N[Z];

    /* rest of */
    m_mOCS[X][W] = m_mOCS[Y][W] = m_mOCS[Z][W] = m_mOCS[W][X]  = m_mOCS[W][Y] = m_mOCS[W][Z] = ZERO;
    m_mOCS[W][W] = ONE;
}

/* arbitrary axis algorythm as defined by Autocad */
void CMatrix::GetArbitraryAxis(AXIS *N, AXIS *Ax, AXIS *Ay)
{
    AXIS Wy[] = {0,1,0}; /* world y axis */
    AXIS Wz[] = {0,0,1}; /* world z axis */

    /* compute Ax vector */
    if(fabs(N[X]) < ARBBOUND && fabs(N[Y]) < ARBBOUND)
           /* Ax = Wy X N where X is cross-product */
        CrossProduct(Ax, Wy, N);
    else
        /* Ax = Wz X N where X is cross-product */
        CrossProduct(Ax, Wz, N);

    /* scale Ax vector */
    ScaleVectorToUnitLength(Ax);

    /* compute Ay vector */
    CrossProduct(Ay, N, Ax);

    /* scale Ay vector */
    ScaleVectorToUnitLength(Ay);
}


/* return square of value */
double CMatrix::Squared(double val)
{
    return val * val;
}

/* compute cross-product of two vectors (axes) */
void CMatrix::CrossProduct(AXIS *Av, AXIS *V1, AXIS *V2)
{
    Av[X] = (V1[Y] * V2[Z]) - (V1[Z] * V2[Y]);
    Av[Y] = (V1[Z] * V2[X]) - (V1[X] * V2[Z]);
    Av[Z] = (V1[X] * V2[Y]) - (V1[Y] * V2[X]);
}

/*
** scale the scale so that when the compents are squared
** they add up to 1
*/
void CMatrix::ScaleVectorToUnitLength(AXIS *Av)
{
    double Len;

    Len = sqrt(Squared(Av[X]) + Squared(Av[Y]) + Squared(Av[Z]));

    /* scale Ax vector to unit length */
    Av[X] /= Len;
    Av[Y] /= Len;
    Av[Z] /= Len;
}

/*
** squares the components of the vector and adds together
*/
void CMatrix::PrintVectorUnitLength(AXIS *Av)
{
    /* display length again of new vector */
    CString strVectorLen;

    strVectorLen.Format("Unit Length: %f", Squared(Av[X]) + Squared(Av[Y]) + Squared(Av[Z]));

    AfxMessageBox(strVectorLen);
}


void CMatrix::InvertMatrix(void)
/* Array of 16 doubles in row-major order */
{
    double a[4][4];
    double b[4],c[4];
    double w,y;
    short z[4];
    short i;
    register short j,k;

    memcpy(a, m_mOCS, sizeof(a));

    z[0]=0; z[1]=1; z[2]=2; z[3]=3;

    for (i=0; i<4; i++) {
        k=i; y=a[i][i];

        for (j=i+1; j<4; j++) {
            w=a[i][j];
            if (fabs(w)>fabs(y)) {
                k=j;
                y=w;
            }
        } /* for j=i+1 */

        y=1.0/y;
        for (j=0; j<4; j++) {
            c[j]=a[j][k];
            a[j][k]=a[j][i];
            a[j][i]= -c[j] * y;
            a[i][j]*=y;
            b[j]=a[i][j];
        }
        a[i][i]=y;
        j=z[i];
        z[i]=z[k];
        z[k]=j;
        for (k=0; k<4; k++)
            if (k!=i)
                for (j=0; j<4; j++)
                    if (j!=i)
                        a[k][j]=a[k][j]-b[j]*c[k];
    }

    for (i=0; i<4; i++) {
        do {
            k=z[i];
            if (k!=i) {
                for (j=0; j<4; j++) {
                    w=a[i][j];
                    a[i][j]=a[k][j];
                    a[k][j]=w;
                }
                j=z[i];
                z[i]=z[k];
                z[k]=j;
            }
        } while (k!=i);
    }

    memcpy(m_mWCS, a, sizeof(a));
}

/*
** translate point to WCS
*/
void CMatrix::TransVectorToWCS(VECTOR *newpt0)
{
    VECTOR pt0[3];

    memcpy(pt0, newpt0, 3 * sizeof(double));

    newpt0[X] = (m_mOCS[X][X] * pt0[X]) + (m_mOCS[Y][X] * pt0[Y]) + (m_mOCS[Z][X] * pt0[Z]) + (m_mOCS[W][X] * ONE);
    newpt0[Y] = (m_mOCS[X][Y] * pt0[X]) + (m_mOCS[Y][Y] * pt0[Y]) + (m_mOCS[Z][Y] * pt0[Z]) + (m_mOCS[W][Y] * ONE);
    newpt0[Z] = (m_mOCS[X][Z] * pt0[X]) + (m_mOCS[Y][Z] * pt0[Y]) + (m_mOCS[Z][Z] * pt0[Z]) + (m_mOCS[W][Z] * ONE);
}


/*
** translate point to OCS
*/
void CMatrix::TransVectorToOCS(VECTOR *newpt0)
{
    VECTOR pt0[3];

    memcpy(pt0, newpt0, 3 * sizeof(double));

    newpt0[X] = (m_mWCS[X][X] * pt0[X]) + (m_mWCS[Y][X] * pt0[Y]) + (m_mWCS[Z][X] * pt0[Z]) + (m_mWCS[W][X] * ONE);
    newpt0[Y] = (m_mWCS[X][Y] * pt0[X]) + (m_mWCS[Y][Y] * pt0[Y]) + (m_mWCS[Z][Y] * pt0[Z]) + (m_mWCS[W][Y] * ONE);
    newpt0[Z] = (m_mWCS[X][Z] * pt0[X]) + (m_mWCS[Y][Z] * pt0[Y]) + (m_mWCS[Z][Z] * pt0[Z]) + (m_mWCS[W][Z] * ONE);
}

免责声明 - 我的代码文件是1999年!但它仍然有效。