我目前正致力于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,但由于挤出矢量可以指向任何方向,我需要一个适当的转换矩阵。
感谢任何帮助。
托马斯
答案 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年!但它仍然有效。