home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
MATLIB
/
SETMAT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-22
|
12KB
|
491 lines
/*
* 行列演算ライブラリ
*
* 1994.6.5 Copyright T.Kobayashi
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "lib.h"
#include "_matclas.h"
#include "inlib.h"
int MatrixClassID ;
extern int VectorClassID ;
static DataStruct UnitMatrix ;
static IntData RotConst[3] = {
{TYPE_INT, 0, AxisX},
{TYPE_INT, 0, AxisY},
{TYPE_INT, 0, AxisZ},
};
static MatrixClass *StackAllocMatrix( DataStruct* );
static int MatrixToString( int, int, DataStruct* );
static int SysMatAxis( int, int, DataStruct* );
static int SysMatrix( int, int, DataStruct* );
static int SysMatVec( int, int, DataStruct* );
static int SysMatMove( int, int, DataStruct* );
static int SysMatRot( int, int, DataStruct* );
static int SysMatScale( int, int, DataStruct* );
static int SysMatMult( int, int, DataStruct* );
static int SysMatInv( int, int, DataStruct* );
static int SysMatAdd( int, int, DataStruct* );
static int SysMatGetVector( int, int, DataStruct* );
static int SysMatEqual( int, int, DataStruct* );
extern double ToDouble( DataStruct* );
static MatrixClass *StackAllocMatrix( buf )
DataStruct *buf ;
{
DataStruct *top ;
top = StackAlloc( 1 );
top->type = TYPE_OBJECT ;
top->od.ptr = ObjectDup( buf->od.ptr );
return (MatrixClass*)top->od.ptr ;
}
double ToDouble( buf )
DataStruct *buf ;
{
assert( buf->type & (TYPE_INT|TYPE_REAL) );
if ( buf->type == TYPE_INT )
return (double)buf->id.i ;
else
return (double)buf->rd.r ;
}
int ToVector(int args, DataStruct *buf, Vector* vec)
{
if (args <= 0) {
return 0;
} else if (args >= 3
&& (buf[0].type & (TYPE_INT|TYPE_REAL))
&& (buf[1].type & (TYPE_INT|TYPE_REAL))
&& (buf[2].type & (TYPE_INT|TYPE_REAL))) {
vec->x = ToDouble(&buf[0]);
vec->y = ToDouble(&buf[1]);
vec->z = ToDouble(&buf[2]);
return 3;
} else if (buf->type == TYPE_OBJECT) {
if (ObjectCheck( &buf[0], VectorClassID )) {
VectorClass *v;
v = (VectorClass*)buf->od.ptr ;
vec->x = v->vec.x;
vec->y = v->vec.y;
vec->z = v->vec.z;
return 1;
}
} else if (buf->type == TYPE_ARRAY) {
DataStruct *abuf;
abuf = buf->ad.ary;
if (buf->ad.size >= 3
&& (abuf[0].type & (TYPE_INT|TYPE_REAL))
&& (abuf[1].type & (TYPE_INT|TYPE_REAL))
&& (abuf[2].type & (TYPE_INT|TYPE_REAL))) {
vec->x = ToDouble(&abuf[0]);
vec->y = ToDouble(&abuf[1]);
vec->z = ToDouble(&abuf[2]);
return 1;
}
}
return 0;
}
void InitMatrixLibrary()
{
MatrixClass *mat ;
MatrixClassID = NewClass( "Matrix", 0 );
NewFunction( MatrixClassID, "tostring", MatrixToString );
NewFunction( 0, "Matrix", SysMatrix );
NewFunction( MatrixClassID, "vec", SysMatVec );
NewFunction( MatrixClassID, "axis", SysMatAxis );
NewFunction( MatrixClassID, "move", SysMatMove );
NewFunction( MatrixClassID, "rot", SysMatRot );
NewFunction( MatrixClassID, "scale", SysMatScale );
NewFunction( MatrixClassID, "getvector", SysMatGetVector );
NewOperator( MatrixClassID, OPE_MULT, SysMatMult );
NewOperator( MatrixClassID, OPE_DIVIDE, SysMatInv );
NewOperator( MatrixClassID, OPE_PLUS, SysMatAdd );
NewOperator( MatrixClassID, OPE_MINUS, SysMatAdd );
NewOperator( MatrixClassID, OPE_EQ, SysMatEqual );
NewOperator( MatrixClassID, OPE_NOTEQ, SysMatEqual );
UnitMatrix.type = TYPE_OBJECT ;
UnitMatrix.od.ptr = ObjectAlloc( sizeof( Matrix ), MatrixClassID );
mat = (MatrixClass*)UnitMatrix.od.ptr ;
MatUnit( mat->mat );
NewConst( "UNIT_MATRIX", &UnitMatrix );
NewConst( "AXISX", (DataStruct*)&RotConst[0] );
NewConst( "AXISY", (DataStruct*)&RotConst[1] );
NewConst( "AXISZ", (DataStruct*)&RotConst[2] );
}
/* 表示 */
static int MatrixToString( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
char str[256] ;
MatrixClass *m ;
assert( buf->type == TYPE_OBJECT );
m = (MatrixClass*)buf->od.ptr ;
sprintf( str,
" %10.4f %10.4f %10.4f\n"
" %10.4f %10.4f %10.4f\n"
" %10.4f %10.4f %10.4f\n"
" %10.4f %10.4f %10.4f\n",
m->mat[0][0], m->mat[0][1], m->mat[0][2],
m->mat[1][0], m->mat[1][1], m->mat[1][2],
m->mat[2][0], m->mat[2][1], m->mat[2][2],
m->mat[3][0], m->mat[3][1], m->mat[3][2] );
buf = StackAlloc( 1 );
StringToObject( buf, str );
return RETURN_RETURN ;
}
/* 行列の設定 */
static int SysMatrix( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
int i, j ;
MatrixClass *m ;
DataStruct *top ;
#if 0
ArgCheck( "axis", args, buf,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_NOASN );
top = StackAlloc( 1 );
top->type = TYPE_OBJECT ;
top->od.ptr = ObjectAlloc( sizeof( Matrix ), MatrixClassID );
m = (MatrixClass*)top->od.ptr ;
for( i = 0 ; i < 4 ; i++ )
{
for( j = 0 ; j < 3 ; j++ )
m->mat[i][j] = ToDouble( &buf[i*3+j] );
}
#endif
Vector v[4];
int i0, i1, i2, i3;
if ((i0 = ToVector(args, buf, &v[0])) == 0
|| (i1 = ToVector(args-i0, buf+i0, &v[1])) == 0
|| (i2 = ToVector(args-i0-i1, buf+i0+i1, &v[2])) == 0) {
ExecError( "Matrix: 引数の型が不正です。" );
}
if ((i3 = ToVector(args-i0-i1-i2, buf+i0+i1+i2, &v[3])) == 0) {
v[3].x = v[3].y = v[3].z = 0.0;
}
top = StackAlloc( 1 );
top->type = TYPE_OBJECT ;
top->od.ptr = ObjectAlloc( sizeof( Matrix ), MatrixClassID );
m = (MatrixClass*)top->od.ptr ;
for( i = 0 ; i < 4 ; i++ )
{
m->mat[i][0] = v[i].x;
m->mat[i][1] = v[i].y;
m->mat[i][2] = v[i].z;
}
return RETURN_RETURN ;
}
/* 軸変換の行列生成 */
static int SysMatAxis( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
ArgCheck( "axis", args, buf, TYPE_OBJECT, TYPE_INT, TYPE_INT, TYPE_NOASN );
m = StackAllocMatrix( &buf[0] );
MatAxis( m->mat, buf[1].id.i, buf[2].id.i );
return RETURN_RETURN ;
}
/* ベクトル指定の行列生成 */
static int SysMatVec( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
#if 0
VectorClass *vec1, *vec2 ;
ArgCheck( "axis", args, buf, TYPE_OBJECT,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL,
TYPE_NOASN );
m = StackAllocMatrix( &buf[0] );
vec1 = (VectorClass*)buf[1].od.ptr ;
vec2 = (VectorClass*)buf[2].od.ptr ;
MatVec( m->mat,
ToDouble( &buf[1] ), ToDouble( &buf[2] ), ToDouble( &buf[3] ),
ToDouble( &buf[4] ), ToDouble( &buf[5] ), ToDouble( &buf[6] ) );
#endif
Vector v0, v1;
int i0, i1;
if ((i0 = ToVector(args, buf+1, &v0)) == 0
|| (i1 = ToVector(args-i0,buf+1+i0,&v1)) == 0) {
ExecError( "vec: 引数の型が不正です。" );
}
m = StackAllocMatrix( &buf[0] );
MatVec(m->mat, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z);
return RETURN_RETURN ;
}
/* 平行移動の行列合成 */
static int SysMatMove( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
#if 0
ArgCheck( "move", args, buf, TYPE_OBJECT,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_NOASN );
m = StackAllocMatrix( &buf[0] );
MatMove( m->mat, ToDouble( &buf[1] ), ToDouble( &buf[2] ), ToDouble( &buf[3] ) );
#endif
Vector v;
if (ToVector(args, buf+1, &v) == 0) {
ExecError( "move: 引数の型が不正です。" );
}
m = StackAllocMatrix( &buf[0] );
MatMove(m->mat, v.x, v.y, v.z);
return RETURN_RETURN ;
}
/* 回転の行列合成 */
static int SysMatRot( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
ArgCheck( "rot", args, buf, TYPE_OBJECT, TYPE_INT, TYPE_INT|TYPE_REAL, TYPE_NOASN );
m = StackAllocMatrix( &buf[0] );
MatRot( m->mat, buf[1].id.i, ToDouble( &buf[2] ) );
return RETURN_RETURN ;
}
/* スケールの行列生成 */
static int SysMatScale( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
#if 0
ArgCheck( "scale", args, buf, TYPE_OBJECT,
TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_INT|TYPE_REAL, TYPE_NOASN );
m = StackAllocMatrix( &buf[0] );
MatScale( m->mat, ToDouble( &buf[1] ), ToDouble( &buf[2] ), ToDouble( &buf[3] ) );
#endif
Vector v;
if (ToVector(args, buf+1, &v) == 0) {
ExecError( "move: 引数の型が不正です。" );
}
m = StackAllocMatrix( &buf[0] );
MatScale(m->mat, v.x, v.y, v.z);
return RETURN_RETURN ;
}
/* スケールの行列生成 */
static int SysMatGetVector( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m ;
VectorClass *v ;
int n;
m = (MatrixClass*)buf[0].od.ptr;
if (buf[1].type == TYPE_ARRAY) {
ArgCheck( "getvector", args, buf, TYPE_OBJECT, TYPE_ARRAY, TYPE_NOASN );
if (buf[1].ad.size < 4) {
ExecError("引数の配列の要素数が足りません。(getvector)");
}
buf = buf[1].ad.ary;
for (n = 0; n < 4; ++n) {
v = (VectorClass*)ObjectAlloc( sizeof( VectorClass ), VectorClassID );
v->vec.x = m->mat[n][0];
v->vec.y = m->mat[n][1];
v->vec.z = m->mat[n][2];
buf[n].type = TYPE_OBJECT;
buf[n].od.ptr = (Object*)v;
}
return RETURN_VOID ;
} else {
ArgCheck( "getvector", args, buf, TYPE_OBJECT, TYPE_INT, TYPE_NOASN );
n = buf[1].id.i;
if (n < 0 || n >= 4) {
StackPushBoolean(FALSE);
} else {
v = (VectorClass*)ObjectAlloc( sizeof( VectorClass ), VectorClassID );
v->vec.x = m->mat[n][0];
v->vec.y = m->mat[n][1];
v->vec.z = m->mat[n][2];
buf = StackAlloc( 1 );
buf->type = TYPE_OBJECT ;
buf->od.ptr = (Object*)v ;
}
}
return RETURN_RETURN ;
}
/* 行列の積 */
static int SysMatMult( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
double a ;
MatrixClass *m1, *m2, *m ;
assert( buf[0].type == TYPE_OBJECT );
m = StackAllocMatrix( &buf[0] );
if ( ObjectCheck( &buf[1], MatrixClassID ) )
{
m1 = (MatrixClass*)buf[0].od.ptr ;
m2 = (MatrixClass*)buf[1].od.ptr ;
MatMult( m->mat, m1->mat, m2->mat );
}
else if ( buf[1].type & (TYPE_INT|TYPE_REAL) )
{
a = ToDouble( &buf[1] );
MatScale( m->mat, a, a, a );
}
else
{
ExecError( "型が不正です。(演算子*)" );
}
return RETURN_RETURN ;
}
/* 逆行列 */
static int SysMatInv( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m1, *m2 ;
Matrix mat ;
assert( buf[0].type == TYPE_OBJECT );
m1 = StackAllocMatrix( &buf[0] );
if ( ObjectCheck( &buf[1], MatrixClassID ) )
{
m2 = (MatrixClass*)buf[1].od.ptr ;
MatCopy( mat, m2->mat );
MatInv( mat );
MatMult( m1->mat, m1->mat, mat );
}
else
{
ExecError( "型が不正です。(演算子/)" );
}
return RETURN_RETURN ;
}
static int SysMatAdd( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m1, *m2 ;
assert( buf[0].type == TYPE_OBJECT );
if ( ObjectCheck( &buf[1], MatrixClassID ) )
{
m1 = StackAllocMatrix( &buf[0] );
m2 = (MatrixClass*)buf[1].od.ptr ;
switch( ident )
{
case OPE_PLUS:
MatAdd( m1->mat, m1->mat, m2->mat );
break ;
case OPE_MINUS:
MatSub( m1->mat, m1->mat, m2->mat );
break ;
default:
assert( FALSE );
}
}
return RETURN_RETURN ;
}
static int SysMatEqual( ident, args, buf )
int ident ;
int args ;
DataStruct *buf ;
{
MatrixClass *m1, *m2 ;
int flag;
int i, j;
assert( buf[0].type == TYPE_OBJECT );
if ( ObjectCheck( &buf[1], MatrixClassID ) )
{
m1 = (MatrixClass*)buf[0].od.ptr ;
m2 = (MatrixClass*)buf[1].od.ptr ;
flag = TRUE;
for( i = 0 ; i < 4 ; i++ )
{
for( j = 0 ; j < 3 ; j++ ) {
flag &= (m1->mat[i][j] == m2->mat[i][j]);
}
}
switch( ident )
{
case OPE_EQ:
StackPushBoolean(flag);
break ;
case OPE_NOTEQ:
StackPushBoolean(!flag);
break ;
default:
assert( FALSE );
}
return RETURN_RETURN;
}
return RETURN_VOID ;
}