home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vis-ftp.cs.umass.edu
/
vis-ftp.cs.umass.edu.tar
/
vis-ftp.cs.umass.edu
/
pub
/
Software
/
ASCENDER
/
poly2curves.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-24
|
16KB
|
713 lines
#include "../polygons.h"
#define EXPECTED_CONVERGENCE 250
#define EPSILON 0.0001
int singular(float **M, int n);
#define TINY 1.0e-8
/******************************************************************************
Christopher Jaynes
Feb 7, 1994
These routines take the final polygon set from the Feature
Relation Graph and draw the polygons selected as the maximal
independent subset of cycles and display them as an overlay on
the image.
The polygons
***************************************************************************/
void constraints_3d(vertexList *vert);
void poly2curves(c_handle pane, MGvertexList *MetaGraph, c_handle im)
{
MGedgeList *MG;
vertexList *vert;
vertexList *ptr;
int index=0;
int i=0;
c_handle world;
c_handle RCDEcurve;
c_handle polygons_fs;
MG = MetaGraph->eList;
if (MG == NULL)
fprintf(stderr,"ERRORRRRRRR!\n");
/** Make the 2d Feature Set to contain the rooptop polygons **/
world = get_2d_world(im);
polygons_fs = get_fs_named("UMass 2d Buildings",world);
while (MG != NULL) {
vert = MG->vertex->vList;
if (vert == NULL)
fprintf(stderr,"Polygon with no Vertecies !\n");
/** Impose constraints on this polygon **/
if (CONSTRAIN)
constraints_3d(vert);
i=0;
RCDEcurve = make_2d_building_curve(TRUE,world);
while (vert != NULL) {
if (CONSTRAIN)
add_vertex_internal(RCDEcurve,i,
vert->vertex->xpos,
vert->vertex->ypos,0.0);
else
add_vertex_internal(RCDEcurve,i,
(double)vert->vertex->x,
(double)vert->vertex->y,0.0);
vert = vert->next;
i++;
}
while (number_of_vertices(RCDEcurve) > i)
delete_vertex_internal(RCDEcurve,i+1);
add_object(RCDEcurve,polygons_fs);
index++;
MG = MG->next;
}
expose_feature_set(polygons_fs,top_view(1,in_pane));
}
/*
* Constraints:
*
* Use world knowledge about the shape of the polygons to choose a
* least squares solution for the position of the vertecies according
* to orthogonality, parallelism.
*
*/
#define MAXVERT 20
float V[2*MAXVERT]; /* Vector of variables (x,y) */
float M[2*MAXVERT]; /* Vector of measurments (u,v) */
float C[MAXVERT]; /* Constraint equations (evaluated at M) */
float L[MAXVERT]; /* Lambda */
float J[MAXVERT][2*MAXVERT]; /* Jacobian of C, with respect to V */
float R[MAXVERT]; /* J x M */
float Theta[MAXVERT]; /* Angle Constraints imposed on the polygon */
float Z[MAXVERT];
float **A;
float *B;
/** Function Prototypes **/
float nextX(int i, int n);
float prevX(int i, int n);
float nextY(int i, int n);
float prevY(int i, int n);
float norm(float x1,float y1,float x2,float y2);
float Mx(int i);
float My(int i);
float error(int n);
float normN(int i, int n);
float normP(int i, int n);
void computeR(int n);
void buildA(int n);
void buildB(int n);
void loadC(int n);
void loadJ(int n);
void initA(int n);
void init(int n);
float **As, **vs;
float *ws;
void constraints_3d(vertexList *vert)
/*
* Backproject the polygon edges into a horizonal plane,
* impose the constraints on the final 3D shape of the polygon
* using a least-squares method.
*
* Re-project the solution to capture the final polygon shape
* in the image coordinates.
*
*/
{
int N; /* Number of datapoints */
int *Index;
float d;
float e;
mat_4x1 point, result;
int i,j,k;
int count=0;
N = loadM_in3D(vert);
j=0;
Index = (int *)vector(1,3*N);
A = matrix(1,3*N,1,3*N);
B = vector(1,3*N);
e = 1.0;
while (e > EPSILON) {
init(N);
loadC(N);
loadJ(N);
computeR(N);
initA(N);
buildA(N);
if (singular(A,3*N)) {
while (vert != NULL) {
vert->vertex->xpos = (double)vert->vertex->x;
vert->vertex->ypos = (double)vert->vertex->y;
vert = vert->next;
}
return;
}
ludcmp(A,(3*N),Index,&d);
for (j=1; j <= N; j++)
d *= A[j][j];
if (fabs(d) <= EPSILON){/* If so, return leave polygon as is. */
while (vert != NULL) {
vert->vertex->xpos = (double)vert->vertex->x;
vert->vertex->ypos = (double)vert->vertex->y;
vert = vert->next;
}
return;
}
buildB(N);
lubksb(A,(3*N),Index,B);
e = error(N);
loadM_in3D(NULL,N);
if (count > EXPECTED_CONVERGENCE)
break;
count++;
}
/** NOTE: The solution has been computed in a 3D, horizontal plane.
reproject the points into the image coordinate system. **/
j = 1;
i=0;
while (vert != NULL) {
point[0] = B[j++];
point[1] = B[j++];
point[2] = Z[i++];
point[3] = 1.0;
project_3d_to_2d(IMAGE_NAME,point,result);
vert->vertex->xpos = result[0];
vert->vertex->ypos = result[1];
/*
vert->vertex->x = (int) floor(result[0]);
vert->vertex->y = (int) floor(result[1]);
*/
vert = vert->next;
}
free_matrix(A,1,3*N,1,3*N);
free_vector(B,1,3*N);
free_matrix(As,1,3*N,1,3*N);
free_matrix(vs,1,3*N,1,3*N);
free_vector(ws,1,3*N);
}
int loadM_in3D(vertexList *v, int n)
{
int i = 0;
int j;
float temp;
mat_4x1 point, result;
/* When v is NULL, we should copy the current solution
from B, into M */
i=0;
if (v == NULL) {
for (i=0; i < 2*n; i++)
M[i] = B[i+1];
} else {
i=0; j = 0;
while (v != NULL) {
point[0] = (double) v->vertex->x;
point[1] = (double) v->vertex->y;
point[2] = 0.0;
point[3] = 1.0;
project_2d_to_KP(IMAGE_NAME,point,result);
M[j++] = (float) result[0];
M[j++] = (float) result[1];
Z[i] = result[2];
Theta[i++] = M_PI_2;
v = v->next;
}
}
return(i);
}
float prevX(int i, int n)
{
if (i == 0)
return(M[(2*n)-2]);
else
return(M[(2*i)-2]);
}
float nextX(int i, int n)
{
if (i == (n-1))
return(M[0]);
else
return(M[(2*i)+2]);
}
float prevY(int i, int n)
{
if (i == 0)
return(M[(2*n)-1]);
else
return(M[(2*i)-1]);
}
float nextY(int i, int n)
{
if (i == (n-1))
return(M[1]);
else {
return(M[(2*i)+3]);
}
}
void loadC(int n)
/**
Compute 'C' the Constraint equations at 'M'
Intersecting lines on the polygon are constrained to
meet at the correct angle( right now 90 degrees !). That is:
L1 -- L2 meet at angle Theta[1].
**/
{
int i, j;
for (i=0; i < n; i++) {
C[i] = ((nextX(i,n)-Mx(i))*(Mx(i)-prevX(i,n))) +
((nextY(i,n)-My(i))*(My(i)-prevY(i,n))) -
(normN(i,n)*normP(i,n)*cos(Theta[i]));
}
}
void loadJ(int n)
/**
J is is Jacobian of C with respect to the matrix V (at M)
**/
{
int i, j;
J[0][0] = -2.0*Mx(0) + prevX(0,n) + nextX(0,n)
-0.5*((normP(0,n)*Theta[0]*(-2.0*nextX(0,n) + 2.0*Mx(0))) /
(normN(0,n)))
-0.5*((normN(0,n)*Theta[0]*(-2.0*prevX(0,n) + 2.0*Mx(0))) /
(normP(0,n)));
J[0][1] = -2.0*My(0) + prevY(0,n) + nextY(0,n)
-0.5*((normP(0,n)*Theta[0]* (-2.0*nextY(0,n) + 2.0*My(0))) /
(normN(0,n)))
-0.5*((normP(0,n)*Theta[0]* (-2.0*prevY(0,n) + 2.0*My(0))) /
(normN(0,n)));
J[0][2] = -prevX(0,n) + Mx(0) - 0.5*((normP(0,n)*Theta[0]*
(2.0*nextX(0,n) - 2.0*Mx(0)) ) / normN(0,n));
J[0][3] = -prevY(0,n) + My(0) - 0.5*((normP(0,n) * Theta[0]*
(2.0*nextY(0,n) - 2.0*My(0)) ) / normN(0,n));
J[0][(2*n)-2] = -nextX(0,n) + Mx(0) -
0.5*((normN(0,n)*Theta[0]* (2.0*prevX(0,n) - 2.0*Mx(0))) /
normP(0,n));
J[0][(2*n)-1] = -nextY(0,n) + My(0) -
0.5*((normN(0,n)*Theta[0]* (2.0*prevY(0,n) - 2.0*My(0))) /
normP(0,n));
for (i=1,j=0; i < n-1; i++,j= j + 2) {
J[i][j] = -nextX(i,n) + Mx(i) -
0.5*((normN(i,n)*Theta[i]* (2.0*prevX(i,n) - 2.0*Mx(i))) /
normP(i,n));
J[i][j+1] = -nextY(i,n) + My(i) -
0.5*((normN(i,n)*Theta[i]* (2.0*prevY(i,n) - 2.0*My(i))) /
normP(i,n));
J[i][j+2] = -2.0*Mx(i) + prevX(i,n) + nextX(i,n)
-0.5*((normP(i,n)*Theta[i]* (-2.0*nextX(i,n) + 2.0*Mx(i))) /
(normN(i,n)))
-0.5*((normN(i,n)*Theta[i]* (-2.0*prevX(i,n) + 2.0*Mx(i))) /
(normP(i,n)));
J[i][j+3] = -2.0*My(i) + prevY(i,n) + nextY(i,n)
-0.5*((normP(i,n)*Theta[i]* (-2.0*nextY(i,n) + 2.0*My(i))) /
(normN(i,n)))
-0.5*((normN(i,n)*Theta[i]* (-2.0*prevY(i,n) + 2.0*My(i))) /
(normP(i,n)));
J[i][j+4] = -prevX(i,n) + Mx(i) -
0.5*((normP(i,n)* Theta[i]*(2.0*nextX(i,n) - 2.0*Mx(i))) /
normN(i,n));
J[i][j+5] = -prevY(i,n) + My(i) -
0.5*((normP(i,n)* Theta[i]*(2.0*nextY(i,n) - 2.0*My(i))) /
normN(i,n));
}
J[i][0] = -prevX(i,n) + Mx(i) - 0.5*((normP(i,n)*Theta[i]*
(2.0*nextX(i,n) - 2.0*Mx(i)) ) /
normN(i,n));
J[i][1] = -prevY(i,n) + My(i) - 0.5*((normP(i,n)*Theta[i]*
(2.0*nextY(i,n) - 2.0*My(i)) ) /
normN(i,n));
J[i][j] = -nextX(i,n) + Mx(i) - 0.5*((normN(i,n) *Theta[i]*
(2.0*prevX(i,n) - 2.0*Mx(i))) /
normP(i,n));
J[i][j+1] = -nextY(i,n) + My(i) - 0.5*((normN(i,n) *Theta[i]*
(2.0*prevY(i,n) - 2.0*My(i))) /
normP(i,n));
J[i][j+2] = -2.0*Mx(i) + prevX(i,n) + nextX(i,n)
-0.5*((normP(i,n)*Theta[i]* (-2.0*nextX(i,n) + 2.0*Mx(i))) /
(normN(i,n)))
-0.5*((normN(i,n)*Theta[i]* (-2.0*prevX(i,n) + 2.0*Mx(i))) /
(normP(i,n)));
J[i][j+3] = -2.0*My(i) + prevY(i,n) + nextY(i,n)
-0.5*((normP(i,n)*Theta[i]* (-2.0*nextY(i,n) + 2.0*My(i))) /
(normN(i,n)))
-0.5*((normN(i,n)*Theta[i]* (-2.0*prevY(i,n) + 2.0*My(i))) /
(normP(i,n)));
}
void buildB(int n)
/* -2m
Cm -Jm *M
Here, Jm*M is stored in the matrix R, result of the
Jacobian(nx2n) * M (2nx1).
The matrix B, is used to solve the final linearized system
for V. The solution is then used as another inital estimate
for the linearization of C.
**/
{
int i,j;
for (j=0,i=1; i <= 2*n; j++,i++)
B[i] = 2.0*M[j];
for(j=0,i=2*n+1; i <= 3*n; i++,j++) {
B[i] = R[j] - C[j];
}
}
void buildA(int n)
{
int i, j, k;
int l;
/** Upper left is 2*I **/
for (i=1; i <= (2*n); i++)
A[i][i] = 2.0;
/** Lower left is the jacobian J **/
for (k=0,i=(2*n)+1; i <= 3*n; k++,i++)
for(l=0,j=1; j <= (2*n); l++,j++)
A[i][j] = J[k][l];
/** Lower right is zero **/
for (i=(2*n)+1; i <= 3*n; i++)
for (j=(2*n)+1; j <= 3*n; j++)
A[i][j] = 0.0;
/** Upper right is transpose of J **/
for (k=0,i=(2*n)+1; i <= 3*n; k++,i++)
for (l=0,j=1; j <= 2*n; l++,j++)
A[j][i] = J[k][l];
}
void
computeR(int n)
{
/* R is the Matrix - Vector Product of the Jacobian J and the parameter
vector V */
int i;
int j;
for (i=0; i < n; i++)
for (j=0; j < (2*n); j++)
R[i] += J[i][j] * M[j];
}
void initA(int n)
{
int i, j;
for (i=1; i <=(3*n); i++)
for (j=1; j <=(3*n); j++)
A[i][j] = 0.0;
}
void init(int n)
{
int i,j;
for (i=0; i < n; i++)
for (j = 0; j < 2*n; j++)
J[i][j] = 0.0;
for (i=0; i < n; i ++)
R[i] = 0.0;
}
float Mx(int i)
{
return(M[2*i]);
}
float My(int i)
{
return(M[(2*i)+1]);
}
float norm(float x1,float y1,float x2,float y2)
{
return( (float)sqrt( ((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2))));
}
float error(int n)
{
int i;
float e;
e = 0.0;
for (i = 0; i < (2*n); i++) {
e += (M[i]-B[i+1])*(M[i] - B[i+1]);
}
return(sqrt(e));
}
float normP(int i, int n)
{
return( norm(prevX(i,n),prevY(i,n),Mx(i),My(i)) );
}
float normN(int i, int n)
{
return( norm(nextX(i,n),nextY(i,n),Mx(i),My(i)) );
}
/*************************************
Get 3d stuff -----
****/
void poly2_3dcurves(c_handle pane, MGvertexList *MetaGraph)
{
c_handle world3d;
c_handle *features;
c_handle RCDEcurve;
c_handle im;
c_handle view;
c_handle obj_matrix;
c_handle obj_trans;
c_handle extrudedCurve;
mat_4x1 p, result;
MGedgeList *MG;
vertexList *vert;
vertexList *tempPtr;
int index=0;
int i=0;
int closed=1;
c_handle poly_fs;
double avgHeight=0.0;
int count;
world3d = get_3d_world_named(IMAGE_NAME_3D);
view = top_view(1,in_pane);
poly_fs = get_fs_named("UMass 3d Buildings",world3d);
MG = MetaGraph->eList;
if (MG == NULL)
fprintf(stderr,"ERRORRRRRRR!\n");
while (MG != NULL) {
vert = MG->vertex->vList;
if (vert == NULL)
fprintf(stderr,"Polygon with no Vertecies !\n");
/** Impose constraints on this polygon **/
if (CONSTRAIN)
constraints_3d(vert);
tempPtr = vert;
avgHeight = 0.0;
count = 0;
while (tempPtr != NULL) {
avgHeight += vert->vertex->height;
count++;
tempPtr = tempPtr->next;
}
avgHeight = avgHeight / (double)count;
i=0;
RCDEcurve = make_3d_closed_curve(6,&world3d);
while (vert != NULL) {
p[0] = (double)vert->vertex->x;
p[1] = (double)vert->vertex->y;
p[2] = avgHeight;
p[3] = 1.0;
project_2d_to_KP(IMAGE_NAME,p,result);
add_vertex_internal(RCDEcurve,i,
result[0],result[1],
avgHeight);
vert = vert->next;
i++;
}
while (number_of_vertices(RCDEcurve) > i)
delete_vertex_internal(RCDEcurve,i+1);
select_fs(world3d,poly_fs);
extrudedCurve = extrude_roof_curve(RCDEcurve);
index++;
MG = MG->next;
}
expose_feature_set(poly_fs,top_view(1,in_pane));
}
c_handle get_fs_named(char *Fname, c_handle wld)
{
c_handle *features;
int done=FALSE;
features = (c_handle *)get_feature_sets(wld,0);
while (!done && *features != -1) {
if (strcmp((char *)name(*features),Fname) == 0)
return(*features);
else
features++;
}
}
int singular(float **M, int n)
/*
* Compute a determinant of matrix M, size n.
*
*/
{
int i,j;
float big,temp;
As = matrix(1,n,1,n);
vs = matrix(1,n,1,n);
ws = vector(1,n);
for (i=1; i <=n; i++)
for (j=1; j <=n; j++)
As[i][j] = M[i][j];
svdcmp(As,n,n,ws,vs);
for (i=1; i <n; i++) {
if (ws[i] < TINY) {
return(TRUE);
}
}
return(FALSE);
/**
for (i=1; i < n; i++) {
big = 0.0;
for (j=1; j<=n; j++)
if ((temp=fabs(M[i][j])) > big) big=temp;
if (big < TINY) {
return(TRUE);
}
}
return(FALSE);
***/
}