home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
174.lha
/
BezSurf
/
mapcalc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
5KB
|
249 lines
#include <math.h>
#include "mytypes.h"
#include "revolve.h" /* need to get scrnpair from here */
#include "mapstuff.h"
#include "menuexp.h"
#ifdef TEST
#undef DebugOn
#define DebugOn 1
#endif TEST
#define DEBUG
/*
* this section of code derived from:
* "The essential algorithms of ray tracing" by Eric Haines
* presented in Sigraph proceedings on Ray Tracing
* my major change has been to simplify it for two dimensions
*/
typedef struct {
float x, y;
} Vector;
static float DotVector(a,b)
Vector *a, *b;
{
return( a->x * b->x + a->y * b->y);
}
static void DivVector(in, scale, out)
Vector *in, *out;
float scale;
{
if ( fabs(scale) < SingleTinyVal ) {
out->x = SingleLargeVal;
out->y = SingleLargeVal;
}
else {
out->x = in->x / scale;
out->y = in->y / scale;
}
}
static Vector Na, Nb, Nc;
static float Du0, Du1, Du2,
Dv0, Dv1, Dv2;
static Vector Qux, Quy,
Qvx, Qvy;
static float Dux, Duy,
Dvx, Dvy;
static bool IsQuadu, IsQuadv;
void CalcMapConsts(vp)
register ScrnPair *vp;
#define p00 vp[0]
#define p01 vp[1]
#define p11 vp[2]
#define p10 vp[3]
{
Vector Pa, Pb, Pc, Pd;
Pa.x = p00.x - p10.x + p11.x - p01.x;
Pa.y = p00.y - p10.y + p11.y - p01.y;
Pb.x = p10.x - p00.x;
Pb.y = p10.y - p00.y;
Pc.x = p01.x - p00.x;
Pc.y = p01.y - p00.y;
Pd.x = p00.x;
Pd.y = p00.y;
Na.x = Pa.y; Na.y = -Pa.x;
Nc.x = Pc.y; Nc.y = -Pc.x;
Nb.x = Pb.y; Nb.y = -Pb.x;
Du0 = DotVector(&Nc, &Pd);
Du1 = DotVector(&Na, &Pd) + DotVector(&Nc, &Pb);
Du2 = DotVector( &Na, &Pb);
if( fabs( Du2 ) > SingleTinyVal ) {
float TwoDu2;
IsQuadu = true;
TwoDu2 = 2.0 * Du2;
DivVector( &Na, TwoDu2, &Qux );
DivVector( &Nc, -Du2, &Quy );
Duy = Du0/Du2;
Dux = -Du1/TwoDu2;
}
else {
IsQuadu = false;
}
Dv0 = DotVector( &Nb, &Pd);
Dv1 = DotVector(&Na, &Pd) + DotVector(&Nb, &Pc);
Dv2 = DotVector( &Na, &Pc);
if( fabs( Dv2 ) > SingleTinyVal ) {
float TwoDv2;
IsQuadv = true;
TwoDv2 = 2.0 * Dv2;
DivVector( &Na, TwoDv2, &Qvx);
DivVector( &Nb, -Dv2, &Qvy);
/* DivVector( &Nc, -Dv2, &Qvy); */
Dvx = - Dv1/TwoDv2;
Dvy = Dv0/Dv2;
}
else {
IsQuadv = false;
}
#ifdef DEBUG
if( DebugOn ) {
printf("du2 %f, du1 %f, du0 %f\n", Du2, Du1, Du0 );
printf("dv2 %f, dv1 %f, dv0 %f\n", Dv2, Dv1, Dv0 );
printf("Na = (%f, %f), Nb = (%f,%f), Nc = (%f,%f)\n",
Na.x, Na.y, Nb.x, Nb.y, Nc.x, Nc.y );
printf("IsQuad =(%c, %c)\n", IsQuadu?'t':'f', IsQuadv? 't': 'f' );
}
#endif DEBUG
}
/*
* given points px,py in the quadrilateral, map them to points inside a
* unit square
*/
void MapXYRatio(px, py, outx, outy, SweepCode)
float px, py;
float *outx, *outy;
short SweepCode;
{
float resu, resv;
Vector Ri;
Ri.x = px; Ri.y = py;
if( !IsQuadu ) {
float denom;
denom = (Du1 - DotVector(&Na, &Ri));
if( fabs(denom) < SingleTinyVal )
resu = 2.0;
else
resu = (DotVector(&Nc, &Ri) - Du0)/denom;
} else {
float Ka, Kb;
float discrim;
Ka = Dux + DotVector( &Qux, &Ri);
Kb = Duy + DotVector( &Quy, &Ri);
discrim = sqrt(fabs(Ka * Ka - Kb));
resu = Ka + ((discrim > Ka)? discrim: (-discrim));
#ifdef DEBUG
if( DebugOn ) {
printf("dux=%f, duy = %f, ka = %f, kb = %f\n",
Dux, Duy, Ka, Kb );
}
#endif DEBUG
}
if( !IsQuadv ) {
float denom;
denom = (Dv1 - DotVector(&Na, &Ri));
if( fabs(denom) < SingleTinyVal )
resv = 2.0;
else
resv = (DotVector(&Nb, &Ri) - Dv0)/denom;
} else {
float Ka, Kb;
float discrim;
Ka = Dvx + DotVector( &Qvx, &Ri);
Kb = Dvy + DotVector( &Qvy, &Ri);
discrim = sqrt(fabs( Ka * Ka - Kb));
resv = Ka + ((discrim > Ka)? discrim: (-discrim));
#ifdef DEBUG
if( DebugOn ) {
printf("dvx=%f, dvy = %f, ka = %f, kb = %f\n",
Dvx, Dvy, Ka, Kb );
}
#endif DEBUG
}
#ifdef DEBUG
if( DebugOn ) {
printf("(%f,%f) -> (%f, %f)\n", px, py, resu, resv );
}
#endif DEBUG
if( resu > 1.0 || resu < 0.0 ) {
resu = ( SweepCode & MP_XMAX)? 1.0: 0.0;
}
if( resv > 1.0 || resv < 0.0 ) {
resv = ( SweepCode & MP_YMAX)? 1.0: 0.0;
}
*outx = resu; *outy = resv;
}
/*
* here abides testcode
*/
#ifdef TEST
#include <stdio.h>
ReadScrnPair(set, a)
char *set;
ScrnPair *a;
{
int tx, ty;
printf("enter screen pair %s\n",set);
scanf("%d %d", &tx, &ty);
a->x = tx; a->y = ty;
}
ReadLimits(a)
ScrnPair a[];
{
ReadScrnPair("a", &a[0]);
ReadScrnPair("b", &a[1]);
ReadScrnPair("c", &a[2]);
ReadScrnPair("d", &a[3]);
}
main() {
float inx, iny;
float outy, outx;
ScrnPair pts[4];
ReadLimits(pts);
CalcMapConsts(pts);
while(!feof(stdin)) {
printf("enter quadrilateral points\n");
scanf("%f %f", &inx, &iny );
MapXYRatio( inx, iny, &outx, &outy, 0);
printf("p(%f,%f)->p(%f,%f)\n", inx, iny, outx, outy);
}
}
#endif TEST