Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F114317497
geometry.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, May 25, 03:49
Size
8 KB
Mime Type
text/x-c
Expires
Tue, May 27, 03:49 (2 d)
Engine
blob
Format
Raw Data
Handle
26381336
Attached To
R6832 iCAPs public
geometry.c
View Options
/*
* dot dot product
* cross cross product
* determinant determinant of matrix built from three vectors
* pdist distance from point towards origin
* ppdist distance between two points
* plinproj projection of point onto line spanned by two points
* ptriproj projection of point onto plane spanned by three points
* ltrisect intersection of line with plane spanned by three points
* lmoutr compute la/mu parameters for projection on triangle
* routlm compute projection on triangle from la/mu parameters
* ptriside determines on which side of a triangle a point lies
* solang computes solid angle of triangle as seen from origin
*
* (c) 2002 Robert Oostenveld
*
*/
#include <math.h>
#include "geometry.h"
/****************************************************************************/
double dot(double* a, double* b)
{
double ss=0;
ss += a[0]*b[0];
ss += a[1]*b[1];
ss += a[2]*b[2];
return ss;
}
/****************************************************************************/
void cross(double* a, double* b, double* r)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
return;
}
/****************************************************************************/
double determinant(double* a, double* b, double* c)
{
return a[0]*(b[1]*c[2]-c[1]*b[2]) - a[1]*(b[0]*c[2]-c[0]*b[2]) + a[2]*(b[0]*c[1]-c[0]*b[1]);
}
/****************************************************************************/
double pdist(double* v1)
{
double ss=0;
ss += v1[0]*v1[0];
ss += v1[1]*v1[1];
ss += v1[2]*v1[2];
return sqrt(ss);
}
/****************************************************************************/
double ppdist(double* v1, double* v2)
{
double ss=0;
ss += (v1[0]-v2[0])*(v1[0]-v2[0]);
ss += (v1[1]-v2[1])*(v1[1]-v2[1]);
ss += (v1[2]-v2[2])*(v1[2]-v2[2]);
return sqrt(ss);
}
/****************************************************************************/
double plinproj(double* l1, double* l2, double* r, double *proj, int flag)
{
double l12[3], l1r[3];
double l12_l=0, l1r_l=0, la=0;
int k;
for (k=0; k<3; k++)
{
l12[k]=l2[k]-l1[k];
l1r[k]=r[k]-l1[k];
l12_l += l12[k]*l12[k];
l1r_l += l1r[k]*l1r[k];
}
l12_l = sqrt(l12_l);
l1r_l = sqrt(l1r_l);
if (l12_l==0)
{
/* begin and endpoint of linepiece are the same */
proj[0] = l1[0];
proj[1] = l1[1];
proj[2] = l1[2];
return l1r_l;
}
if (l1r_l==0)
{
/* point lies exactly at beginpoint of linepiece */
proj[0] = l1[0];
proj[1] = l1[1];
proj[2] = l1[2];
return 0;
}
/* compute relative distance along linepiece */
la = dot(l12,l1r)/(l12_l*l12_l);
if (flag && la<0)
/* intended projection point would lie before begin of linepiece */
la=0;
else if (flag && la>1)
/* intended projection point would lie after end of linepiece */
la=1;
/* compute projection point along line through l1 and l2 */
proj[0] = l1[0] + la*l12[0];
proj[1] = l1[1] + la*l12[1];
proj[2] = l1[2] + la*l12[2];
return ppdist(proj,r);
}
/****************************************************************************/
double ptriproj(double* v1, double* v2, double* v3, double* r, double* proj, int flag)
{
double la, mu, d;
lmoutr(v1, v2, v3, r, &la, &mu, &d);
if (flag)
{
/* projection of r on triangle */
if (la>=0 && mu>=0 && (la+mu)<=1)
routlm(v1, v2, v3, la, mu, proj);
else if (la<0)
d = plinproj(v1, v3, r, proj, flag);
else if (mu<0)
d = plinproj(v1, v2, r, proj, flag);
else
d = plinproj(v2, v3, r, proj, flag);
}
else
{
/* projection of r on plane */
routlm(v1, v2, v3, la, mu, proj);
}
return d;
}
/****************************************************************************/
void ltrisect(double* v1, double* v2, double* v3, double* l1, double* l2, double* proj)
{
double la1, mu1, d1;
double la2, mu2, d2;
double p1[3];
double p2[3];
int s1, s2;
char str[256];
s1 = ptriside(v1, v2, v3, l1);
s2 = ptriside(v1, v2, v3, l2);
if (s1==0)
{
/* point l1 lies on plane spanned by triangle */
proj[0] = l1[0];
proj[1] = l1[1];
proj[2] = l1[2];
return;
}
else if (s2==0)
{
/* point l2 lies on plane spanned by triangle */
proj[0] = l2[0];
proj[1] = l2[1];
proj[2] = l2[2];
return;
}
lmoutr(v1, v2, v3, l1, &la1, &mu1, &d1);
lmoutr(v1, v2, v3, l2, &la2, &mu2, &d2);
routlm(v1, v2, v3, la1, mu1, p1); /* projection of l1 on plane */
routlm(v1, v2, v3, la2, mu2, p2); /* projection of l2 on plane */
/* d1 and d2 are the distances from l1 and l2 to the plane spanned by v1, v2, v3 */
/* these are used to weigh both projected points to their weighed geometric mean */
d1 *= s1;
d2 *= s2;
if (d1==d2)
{
/* the line is parallel to the plane and does not intersect */
proj[0] = mxGetNaN();
proj[1] = mxGetNaN();
proj[2] = mxGetNaN();
return;
}
proj[0] = (d1*p2[0] - d2*p1[0])/(d1-d2);
proj[1] = (d1*p2[1] - d2*p1[1])/(d1-d2);
proj[2] = (d1*p2[2] - d2*p1[2])/(d1-d2);
return;
}
/****************************************************************************/
void lmoutr(double* v1, double* v2, double* v3, double* r, double *la, double *mu, double *ze)
{
double a[3], b[3], c[3], d[3];
double a_l=0, b_l=0, c_l=0, d_l=0;
double det, det_la, det_mu, det_ze;
int k;
for (k=0; k<3; k++)
{
a[k] = r[k]-v1[k];
b[k] = v2[k]-v1[k];
c[k] = v3[k]-v1[k];
a_l += a[k]*a[k];
b_l += b[k]*b[k];
c_l += c[k]*c[k];
}
a_l = sqrt(a_l);
b_l = sqrt(b_l);
c_l = sqrt(c_l);
if (a_l==0)
{
/* point lies exactly on the first vertex */
*la = 0;
*mu = 0;
*ze = 0;
return;
}
else if (b_l==0 || c_l==0)
{
/* this is a degenerate triangle, not possible to compute la/mu */
*la = mxGetNaN();
*mu = mxGetNaN();
*ze = mxGetNaN();
return;
}
else
{
/* compute vector d orthogonal to the triangle */
cross(b, c, d);
d_l = pdist(d);
/* normalize vector d */
d[0] = d[0]/d_l;
d[1] = d[1]/d_l;
d[2] = d[2]/d_l;
/* solve the system of equations using Cramer's method (method of determinants) */
/* c = la*a + mu*b + ze*o */
det = determinant(b, c, d);
det_la = determinant(a, c, d);
det_mu = determinant(b, a, d);
det_ze = determinant(b, c, a);
*la = det_la/det;
*mu = det_mu/det;
*ze = det_ze/det;
/* since d is an orthonormal vector to the plane, the distance of r */
/* to the plane equals the absolume value of parameter ze */
*ze = ((*ze)<0 ? -(*ze) : +(*ze));
}
return;
}
/****************************************************************************/
void routlm(double* v1, double* v2, double* v3, double la, double mu, double* r)
{
r[0] = (1-la-mu)*v1[0]+la*v2[0]+mu*v3[0];
r[1] = (1-la-mu)*v1[1]+la*v2[1]+mu*v3[1];
r[2] = (1-la-mu)*v1[2]+la*v2[2]+mu*v3[2];
return;
}
/****************************************************************************/
int ptriside(double* v1, double* v2, double* v3, double *r)
{
double val;
double a[3], b[3], c[3], d[3];
int k;
for (k=0; k<3; k++)
{
a[k] = r[k]-v1[k];
b[k] = v2[k]-v1[k];
c[k] = v3[k]-v1[k];
}
cross(b, c, d);
val = dot(a, d);
if (val>0)
return 1;
else if (val<0)
return -1;
else
return 0;
}
/****************************************************************************/
double solang(double *r1, double *r2, double *r3, int *on_triangle)
{
double cp23_x,cp23_y,cp23_z,n1,n2,n3,ip12,ip23,ip13,nom,den;
*on_triangle=0;
cp23_x = r2[1] * r3[2] - r2[2] * r3[1];
cp23_y = r2[2] * r3[0] - r2[0] * r3[2];
cp23_z = r2[0] * r3[1] - r2[1] * r3[0];
nom = cp23_x*r1[0] + cp23_y*r1[1] + cp23_z*r1[2];
n1 = sqrt(r1[0]*r1[0] + r1[1]*r1[1] + r1[2]*r1[2]);
n2 = sqrt(r2[0]*r2[0] + r2[1]*r2[1] + r2[2]*r2[2]);
n3 = sqrt(r3[0]*r3[0] + r3[1]*r3[1] + r3[2]*r3[2]);
ip12 = r1[0]*r2[0] + r1[1]*r2[1] + r1[2]*r2[2];
ip23 = r2[0]*r3[0] + r2[1]*r3[1] + r2[2]*r3[2];
ip13 = r1[0]*r3[0] + r1[1]*r3[1] + r1[2]*r3[2];
den = n1*n2*n3 + ip12*n3 + ip23*n1 + ip13*n2;
if (nom==0 & den<=0)
{
*on_triangle=1;
return 0;
}
return -2.*atan2 (nom,den);
}
Event Timeline
Log In to Comment