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

/***************************************************************************
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;
}