You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
8.1 KiB
284 lines
8.1 KiB
13 years ago
|
/***************************************************************************
|
||
|
qsprojection2d.cpp
|
||
|
-------------------
|
||
|
begin : 01-January-2000
|
||
|
copyright : (C) 2000 by Kamil Dobkowski
|
||
|
email : kamildobk@poczta.onet.pl
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
***************************************************************************/
|
||
|
|
||
|
|
||
|
#include "qsprojection2d.h"
|
||
|
#include<math.h>
|
||
|
|
||
|
|
||
|
|
||
|
QSProjection2D::QSProjection2D()
|
||
|
:QSProjection()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSProjection2D::~QSProjection2D()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::matrixI( Matrix m )
|
||
|
{
|
||
|
int i, j;
|
||
|
for ( j=0; j<3; j++ ) for( i=0; i<3; i++ ) m[j][i] = 0.0;
|
||
|
m[0][0] = 1.0;
|
||
|
m[1][1] = 1.0;
|
||
|
m[2][2] = 1.0;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::multiply( Matrix A, Matrix B )
|
||
|
// apply transformation
|
||
|
// A = B*A
|
||
|
{
|
||
|
int i, j, k;
|
||
|
Matrix result;
|
||
|
|
||
|
for( i=0; i<3; i++ )
|
||
|
for (j=0; j<3; j++ ) {
|
||
|
result[i][j] = 0.0;
|
||
|
for( k=0; k<3; k++ ) result[i][j] += B[i][k]*A[k][j];
|
||
|
}
|
||
|
|
||
|
for( i=0; i<3; i++) for( j=0; j<3; j++) A[i][j] = result[i][j];
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::copy( Matrix dst, const Matrix src )
|
||
|
{
|
||
|
int i, j;
|
||
|
for ( i=0; i<3; i++) for( j=0; j<3; j++ ) dst[i][j] = src[i][j];
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::applyT( Matrix m, double dx, double dy )
|
||
|
// translate
|
||
|
// | 0 0 dx |
|
||
|
// | 0 0 dy |
|
||
|
// | 0 0 1 |
|
||
|
{
|
||
|
Matrix temp;
|
||
|
|
||
|
matrixI( temp );
|
||
|
|
||
|
temp[0][2] = dx;
|
||
|
temp[1][2] = dy;
|
||
|
|
||
|
multiply( m, temp );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::applyS( Matrix m, double sx, double sy )
|
||
|
// scale
|
||
|
// | sx 0 0 |
|
||
|
// | 0 sy 0 |
|
||
|
// | 0 0 1 |
|
||
|
{
|
||
|
Matrix temp;
|
||
|
|
||
|
matrixI( temp );
|
||
|
|
||
|
temp[0][0] = sx ;
|
||
|
temp[1][1] = sy ;
|
||
|
|
||
|
multiply( m, temp );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::applyViewport( Matrix m, double x, double y, double w, double h )
|
||
|
// maps (0,0,1,1) rectangle to the (x,y,w,h) rectangle.
|
||
|
{
|
||
|
applyS( m, w, h );
|
||
|
applyT( m, x, y );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::world2DToCanvasX( double x ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return x*T[0][0] + T[0][2];
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::world2DToCanvasY( double y ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return y*T[1][1] + T[1][2];
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::world2DToCanvasZ( double z ) const
|
||
|
{
|
||
|
return 1.0-z;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::canvasXToWorld2D( double x ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
// it does not depend on y so we can set y==0 and simplify
|
||
|
{
|
||
|
double w = IT[2][0]*x + IT[2][2];
|
||
|
return (x*IT[0][0] + IT[0][2])/w;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::canvasYToWorld2D( double y ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
// it does not depend on x so we can set x==0 and simplify
|
||
|
{
|
||
|
double w = IT[2][1]*y + IT[2][2];
|
||
|
return (y*IT[1][1] + IT[1][2])/w;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
double QSProjection2D::canvasZToWorld2D( double z ) const
|
||
|
{
|
||
|
return 1.0-z;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt2f QSProjection2D::worldTransformation( const Matrix m, const QSPt2f& p ) const
|
||
|
{
|
||
|
double w = m[2][0]*p.x + m[2][1]*p.y + m[2][2];
|
||
|
return QSPt2f( (p.x*m[0][0] + p.y*m[0][1] + m[0][2])/w,
|
||
|
(p.x*m[1][0] + p.y*m[1][1] + m[1][2])/w );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt2f QSProjection2D::world2DToCanvas( const QSPt2f& p ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return QSPt2f( p.x*T[0][0] + p.y*T[0][1] + T[0][2],
|
||
|
p.x*T[1][0] + p.y*T[1][1] + T[1][2] );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt3f QSProjection2D::world2DToCanvas3( const QSPt2f& p ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return QSPt3f( p.x*T[0][0] + p.y*T[0][1] + T[0][2],
|
||
|
p.x*T[1][0] + p.y*T[1][1] + T[1][2],
|
||
|
0.0 );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt2f QSProjection2D::world3DToCanvas( const QSPt3f& p ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return QSPt2f( p.x*T[0][0] + p.y*T[0][1] + T[0][2],
|
||
|
p.x*T[1][0] + p.y*T[1][1] + T[1][2] );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt3f QSProjection2D::world3DToCanvas3( const QSPt3f& p ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
return QSPt3f( p.x*T[0][0] + p.y*T[0][1] + T[0][2],
|
||
|
p.x*T[1][0] + p.y*T[1][1] + T[1][2],
|
||
|
1.0-p.z );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
QSPt3f QSProjection2D::canvas3ToWorld3D( const QSPt3f &pos ) const
|
||
|
// all implementations are slightly modified, simplified worldTransformation() - nothing special
|
||
|
{
|
||
|
QSPt2f p = worldTransformation( IT, QSPt2f(pos.x,pos.y) );
|
||
|
return QSPt3f( p.x, p.y, 1.0-pos.z );
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::inv( Matrix result, const Matrix m )
|
||
|
//
|
||
|
{
|
||
|
double detR = m[0][0]*m[1][1]*m[2][2] +
|
||
|
m[0][1]*m[1][2]*m[2][0] +
|
||
|
m[0][2]*m[1][0]*m[2][1] -
|
||
|
m[0][2]*m[1][1]*m[2][0] -
|
||
|
m[0][0]*m[1][2]*m[2][1] -
|
||
|
m[0][1]*m[1][0]*m[2][2];
|
||
|
|
||
|
if ( detR != 0.0 ) {
|
||
|
result[0][0] = ( m[1][1]*m[2][2] - m[1][2]*m[2][1] ) / detR;
|
||
|
result[1][0] = ( m[1][2]*m[2][0] - m[1][0]*m[2][2] ) / detR;
|
||
|
result[2][0] = ( m[1][0]*m[2][1] - m[1][1]*m[2][0] ) / detR;
|
||
|
result[0][1] = ( m[0][2]*m[2][1] - m[0][1]*m[2][2] ) / detR;
|
||
|
result[1][1] = ( m[0][0]*m[2][2] - m[0][2]*m[2][0] ) / detR;
|
||
|
result[2][1] = ( m[0][1]*m[2][0] - m[0][0]*m[2][1] ) / detR;
|
||
|
result[0][2] = ( m[0][1]*m[1][2] - m[0][2]*m[1][1] ) / detR;
|
||
|
result[1][2] = ( m[0][2]*m[1][0] - m[0][0]*m[1][2] ) / detR;
|
||
|
result[2][2] = ( m[0][0]*m[1][1] - m[0][1]*m[1][0] ) / detR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
|
||
|
void QSProjection2D::setClipRect( double x1, double y1, double x2, double y2 )
|
||
|
{
|
||
|
m_cmin.x = QMIN(x1,x2);
|
||
|
m_cmin.y = QMIN(y1,y2);
|
||
|
m_cmax.x = QMAX(x1,x2);
|
||
|
m_cmax.y = QMAX(y1,y2);
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------------------//
|
||
|
|
||
|
void QSProjection2D::getClipRect( double *x1, double *y1, double *x2, double *y2 ) const
|
||
|
{
|
||
|
if (x1) *x1 = m_cmin.x;
|
||
|
if (y1) *y1 = m_cmin.y;
|
||
|
if (x2) *x2 = m_cmax.x;
|
||
|
if (y2) *y2 = m_cmax.y;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|