예제 #1
0
파일: vpArit.cpp 프로젝트: ricsp/visp
/*
 * La procedure "plane_norme" calcule le vecteur norme orthogonal au plan
 * defini par les 3 points.
 * Entree :
 * np		Le vecteur norme orthogonal au plan.
 * ap, bp, cp	Points formant un repere du plan.
 */
void
plane_norme (Vector *np, Point3f *ap, Point3f *bp, Point3f *cp)
{
	Vector	u, v;

	DIF_COORD3(u,*bp,*ap);	/* base orthonorme (ap, u, v)	*/
	DIF_COORD3(v,*cp,*ap);
	norm_vector (&u);
	norm_vector (&v);
	CROSS_PRODUCT (*np,u,v); 
}
예제 #2
0
파일: vpArit.cpp 프로젝트: ricsp/visp
/*
 * La procedure "rotate_vector" transforme le vecteur
 * par la rotation de sens trigonometrique d'angle et d'axe donnes.
 * Entree :
 * vp		Vecteur a transformer.
 * a		Angle de rotation en degres.
 * axis		Vecteur directeur de l'axe de rotation.
 */
void
rotate_vector (Vector *vp, float a, Vector *axis)
{
	Vector		n, u, v, cross;
	float	f;

	a *= (float)M_PI / (float)180.0;	/* passage en radians		*/

	n = *axis;		/* norme le vecteur directeur	*/
	norm_vector (&n);

	/* 
	 * Avant rotation, vp vaut :
	 *   u + v
	 * Apres rotation, vp vaut :
	 *   u + cos(a) * v + sin(a) * (n^vp)
	 * = u + cos(a) * v + sin(a) * (n^v)
	 * avec u = (vp.n) * n, v = vp-u;
	 * ou "u" est la projection de "vp" sur l'axe "axis",
	 * et "v" est la composante de "vp" perpendiculaire a "axis".
	 */
	f = DOT_PRODUCT(*vp, n);
	u = n;
	MUL_COORD3(u,f,f,f);		/* (vp.n) * n		*/

	DIF_COORD3(v,*vp,u);		/* calcule "v"		*/

	f = (float) cos ((double) a);
	MUL_COORD3(v,f,f,f);		/* v * cos(a)		*/

	CROSS_PRODUCT(cross,n,*vp);
	f = (float) sin ((double) a);
	MUL_COORD3(cross,f,f,f);	/* (n^v) * sin(a)	*/

	SET_COORD3(*vp,
		u.x + v.x + cross.x,
		u.y + v.y + cross.y,
		u.z + v.z + cross.z);
}
예제 #3
0
파일: vpArit.cpp 프로젝트: ricsp/visp
/*
 * La procedure "Rotaxis_to_Matrix" initialise la matrice par la rotation
 * d'angle et d'axe donnes.
 * Si M est la matrice, O l'angle et N le vecteur directeur de l'axe :
 *
 *	M = cos(O) Id3 + (1 - cosO) Nt N + sinO N~
 *
 *	| NxNxverO+  cosO NxNyverO+NzsinO NxNzverO-NxsinO 0 |
 * M =	| NxNyverO-NzsinO NyNyverO+  cosO NyNzverO+NxsinO 0 |
 *	| NxNzverO+NysinO NyNzverO-NxsinO NzNzverO+  cosO 0 |
 *	| 0		  0		  0		  1 |
 *
 *	O	angle de rotation.
 *	N	Vecteur directeur norme de l'axe de rotation.
 *	Nt	Vecteur transpose.
 *	N~	| 0	 Nz	-Ny|
 *		|-Nz	 0	 Nx|
 *		| Ny	-Nx	 0 |
 * Entree :
 * a		Angle de rotation en degres.
 * axis		Vecteur directeur de l'axe de la rotation.
 * m		Matrice a initialiser.
 */
void
Rotaxis_to_Matrix (float a, Vector *axis, Matrix m)
{
	float	cosa;
	float	sina;
	float	vera;	/* 1 - cosa	*/
	Vector		n;	/* vecteur norme*/
	Vector		conv;	/* verO n	*/
	Vector		tilde;	/* sinO n	*/

	a *= (float)M_PI / (float)180.0;	/* passage en radians	*/

	cosa = (float) cos ((double) a);
	sina = (float) sin ((double) a);
	vera = (float)1.0 - cosa;

	n = *axis;	/* norme le vecteur directeur	*/
	norm_vector (&n);
	tilde = conv = n;
	MUL_COORD3(conv,vera,vera,vera);
	MUL_COORD3(tilde,sina,sina,sina);

	m[0][0] = conv.x * n.x + cosa;
	m[0][1] = conv.x * n.y + tilde.z;
	m[0][2] = conv.x * n.z - tilde.y;

	m[1][0] = conv.y * n.x - tilde.z;
	m[1][1] = conv.y * n.y + cosa;
	m[1][2] = conv.y * n.z + tilde.x;

	m[2][0] = conv.z * n.x + tilde.y;
	m[2][1] = conv.z * n.y - tilde.x;
	m[2][2] = conv.z * n.z + cosa;

	m[0][3] = m[2][3] = m[1][3] = 0.0;
	m[3][0] = m[3][1] = m[3][2] = 0.0;
	m[3][3] = 1.0;
}
예제 #4
0
파일: buffer2.c 프로젝트: imincik/pkg-grass
/* input line must be looped */
static void convolution_line(struct line_pnts *Points, double da, double db,
			     double dalpha, int side, int round, int caps,
			     double tol, struct line_pnts *nPoints)
{
    int i, j, res, np;
    double *x, *y;
    double tx, ty, vx, vy, wx, wy, nx, ny, mx, my, rx, ry;
    double vx1, vy1, wx1, wy1;
    double a0, b0, c0, a1, b1, c1;
    double phi1, phi2, delta_phi;
    double nsegments, angular_tol, angular_step;
    double angle0, angle1;
    int inner_corner, turns360;

    G_debug(3, "convolution_line() side = %d", side);

    np = Points->n_points;
    x = Points->x;
    y = Points->y;
    if ((np == 0) || (np == 1))
	return;
    if ((x[0] != x[np - 1]) || (y[0] != y[np - 1])) {
	G_fatal_error(_("Line is not looped"));
	return;
    }

    Vect_reset_line(nPoints);

    if ((da == 0) || (db == 0)) {
	Vect_copy_xyz_to_pnts(nPoints, x, y, NULL, np);
	return;
    }

    side = (side >= 0) ? (1) : (-1);	/* normalize variable */
    dalpha *= PI / 180;		/* convert dalpha from degrees to radians */
    angular_tol = angular_tolerance(tol, da, db);

    i = np - 2;
    norm_vector(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
    elliptic_tangent(side * tx, side * ty, da, db, dalpha, &vx, &vy);
    angle1 = atan2(ty, tx);
    nx = x[i] + vx;
    ny = y[i] + vy;
    mx = x[i + 1] + vx;
    my = y[i + 1] + vy;
    if (!round)
	line_coefficients(nx, ny, mx, my, &a1, &b1, &c1);

    for (i = 0; i <= np - 2; i++) {
	G_debug(4, "point %d, segment %d-%d", i, i, i + 1);
	/* save the old values */
	if (!round) {
	    a0 = a1;
	    b0 = b1;
	    c0 = c1;
	}
	wx = vx;
	wy = vy;
	angle0 = angle1;

	norm_vector(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
	if ((tx == 0) && (ty == 0))
	    continue;
	elliptic_tangent(side * tx, side * ty, da, db, dalpha, &vx, &vy);
	angle1 = atan2(ty, tx);
	nx = x[i] + vx;
	ny = y[i] + vy;
	mx = x[i + 1] + vx;
	my = y[i + 1] + vy;
	if (!round)
	    line_coefficients(nx, ny, mx, my, &a1, &b1, &c1);


	delta_phi = angle1 - angle0;
	if (delta_phi > PI)
	    delta_phi -= 2 * PI;
	else if (delta_phi <= -PI)
	    delta_phi += 2 * PI;
	/* now delta_phi is in [-pi;pi] */
	turns360 = (fabs(fabs(delta_phi) - PI) < 1e-15);
	inner_corner = (side * delta_phi <= 0) && (!turns360);


	/* if <line turns 360> and (<caps> and <not round>) */
	if (turns360 && caps && (!round)) {
	    norm_vector(0, 0, vx, vy, &tx, &ty);
	    elliptic_tangent(side * tx, side * ty, da, db, dalpha, &tx, &ty);
	    Vect_append_point(nPoints, x[i] + wx + tx, y[i] + wy + ty, 0);
	    G_debug(4, " append point (c) x=%.16f y=%.16f", x[i] + wx + tx,
		    y[i] + wy + ty);
	    Vect_append_point(nPoints, nx + tx, ny + ty, 0);	/* nx == x[i] + vx, ny == y[i] + vy */
	    G_debug(4, " append point (c) x=%.16f y=%.16f", nx + tx, ny + ty);
	}

	if ((!turns360) && (!round) && (!inner_corner)) {
	    res = line_intersection(a0, b0, c0, a1, b1, c1, &rx, &ry);
	    if (res == 1) {
		Vect_append_point(nPoints, rx, ry, 0);
		G_debug(4, " append point (o) x=%.16f y=%.16f", rx, ry);
	    }
	    else if (res == 2) {
		/* no need to append point in this case */
	    }
	    else
		G_fatal_error
		    ("unexpected result of line_intersection() res = %d",
		     res);
	}

	if (round && (!inner_corner) && (!turns360 || caps)) {
	    /* we should draw elliptical arc for outside corner */

	    /* inverse transforms */
	    elliptic_transform(wx, wy, 1 / da, 1 / db, dalpha, &wx1, &wy1);
	    elliptic_transform(vx, vy, 1 / da, 1 / db, dalpha, &vx1, &vy1);

	    phi1 = atan2(wy1, wx1);
	    phi2 = atan2(vy1, vx1);
	    delta_phi = side * (phi2 - phi1);

	    /* make delta_phi in [0, 2pi] */
	    if (delta_phi < 0)
		delta_phi += 2 * PI;

	    nsegments = (int)(delta_phi / angular_tol) + 1;
	    angular_step = side * (delta_phi / nsegments);

	    phi1 += angular_step;
	    for (j = 1; j <= nsegments - 1; j++) {
		elliptic_transform(cos(phi1), sin(phi1), da, db, dalpha, &tx,
				   &ty);
		Vect_append_point(nPoints, x[i] + tx, y[i] + ty, 0);
		G_debug(4, " append point (r) x=%.16f y=%.16f", x[i] + tx,
			y[i] + ty);
		phi1 += angular_step;
	    }
	}

	Vect_append_point(nPoints, nx, ny, 0);
	G_debug(4, " append point (s) x=%.16f y=%.16f", nx, ny);
	Vect_append_point(nPoints, mx, my, 0);
	G_debug(4, " append point (s) x=%.16f y=%.16f", mx, my);
    }

    /* close the output line */
    Vect_append_point(nPoints, nPoints->x[0], nPoints->y[0], nPoints->z[0]);
    Vect_line_prune ( nPoints );
}
예제 #5
0
파일: buffer2.c 프로젝트: imincik/pkg-grass
/*
 * This function generates parallel line (with loops, but not like the old ones).
 * It is not to be used directly for creating buffers.
 * + added elliptical buffers/par.lines support
 *
 * dalpha - direction of elliptical buffer major axis in degrees
 * da - distance along major axis
 * db: distance along minor (perp.) axis
 * side: side >= 0 - right side, side < 0 - left side
 * when (da == db) we have plain distances (old case)
 * round - 1 for round corners, 0 for sharp corners. (tol is used only if round == 1)
 */
static void parallel_line(struct line_pnts *Points, double da, double db,
			  double dalpha, int side, int round, int caps, int looped,
			  double tol, struct line_pnts *nPoints)
{
    int i, j, res, np;
    double *x, *y;
    double tx, ty, vx, vy, wx, wy, nx, ny, mx, my, rx, ry;
    double vx1, vy1, wx1, wy1;
    double a0, b0, c0, a1, b1, c1;
    double phi1, phi2, delta_phi;
    double nsegments, angular_tol, angular_step;
    int inner_corner, turns360;

    G_debug(3, "parallel_line()");

    if (looped && 0) {
	/* start point != end point */
	return;
    }

    Vect_reset_line(nPoints);

    if (looped) {
	Vect_append_point(Points, Points->x[1], Points->y[1], Points->z[1]);
    }
    np = Points->n_points;
    x = Points->x;
    y = Points->y;

    if ((np == 0) || (np == 1))
	return;

    if ((da == 0) || (db == 0)) {
	Vect_copy_xyz_to_pnts(nPoints, x, y, NULL, np);
	return;
    }

    side = (side >= 0) ? (1) : (-1);	/* normalize variable */
    dalpha *= PI / 180;		/* convert dalpha from degrees to radians */
    angular_tol = angular_tolerance(tol, da, db);

    for (i = 0; i < np - 1; i++) {
	/* save the old values */
	a0 = a1;
	b0 = b1;
	c0 = c1;
	wx = vx;
	wy = vy;


	norm_vector(x[i], y[i], x[i + 1], y[i + 1], &tx, &ty);
	if ((tx == 0) && (ty == 0))
	    continue;

	elliptic_tangent(side * tx, side * ty, da, db, dalpha, &vx, &vy);

	nx = x[i] + vx;
	ny = y[i] + vy;

	mx = x[i + 1] + vx;
	my = y[i + 1] + vy;

	line_coefficients(nx, ny, mx, my, &a1, &b1, &c1);

	if (i == 0) {
	    if (!looped)
		Vect_append_point(nPoints, nx, ny, 0);
	    continue;
	}

	delta_phi = atan2(ty, tx) - atan2(y[i] - y[i - 1], x[i] - x[i - 1]);
	if (delta_phi > PI)
	    delta_phi -= 2 * PI;
	else if (delta_phi <= -PI)
	    delta_phi += 2 * PI;
	/* now delta_phi is in [-pi;pi] */
	turns360 = (fabs(fabs(delta_phi) - PI) < 1e-15);
	inner_corner = (side * delta_phi <= 0) && (!turns360);

	if ((turns360) && (!(caps && round))) {
	    if (caps) {
		norm_vector(0, 0, vx, vy, &tx, &ty);
		elliptic_tangent(side * tx, side * ty, da, db, dalpha, &tx,
				 &ty);
	    }
	    else {
		tx = 0;
		ty = 0;
	    }
	    Vect_append_point(nPoints, x[i] + wx + tx, y[i] + wy + ty, 0);
	    Vect_append_point(nPoints, nx + tx, ny + ty, 0);	/* nx == x[i] + vx, ny == y[i] + vy */
	}
	else if ((!round) || inner_corner) {
	    res = line_intersection(a0, b0, c0, a1, b1, c1, &rx, &ry);
	    /*                if (res == 0) {
	       G_debug(4, "a0=%.18f, b0=%.18f, c0=%.18f, a1=%.18f, b1=%.18f, c1=%.18f", a0, b0, c0, a1, b1, c1);
	       G_fatal_error("Two consequtive line segments are parallel, but not on one straight line! This should never happen.");
	       return;
	       }  */
	    if (res == 1) {
		if (!round)
		    Vect_append_point(nPoints, rx, ry, 0);
		else {
		    /*                    d = dig_distance2_point_to_line(rx, ry, 0, x[i-1], y[i-1], 0, x[i], y[i], 0,
		       0, NULL, NULL, NULL, NULL, NULL);
		       if ( */
		    Vect_append_point(nPoints, rx, ry, 0);
		}
	    }
	}
	else {
	    /* we should draw elliptical arc for outside corner */

	    /* inverse transforms */
	    elliptic_transform(wx, wy, 1 / da, 1 / db, dalpha, &wx1, &wy1);
	    elliptic_transform(vx, vy, 1 / da, 1 / db, dalpha, &vx1, &vy1);

	    phi1 = atan2(wy1, wx1);
	    phi2 = atan2(vy1, vx1);
	    delta_phi = side * (phi2 - phi1);

	    /* make delta_phi in [0, 2pi] */
	    if (delta_phi < 0)
		delta_phi += 2 * PI;

	    nsegments = (int)(delta_phi / angular_tol) + 1;
	    angular_step = side * (delta_phi / nsegments);

	    for (j = 0; j <= nsegments; j++) {
		elliptic_transform(cos(phi1), sin(phi1), da, db, dalpha, &tx,
				   &ty);
		Vect_append_point(nPoints, x[i] + tx, y[i] + ty, 0);
		phi1 += angular_step;
	    }
	}

	if ((!looped) && (i == np - 2)) {
	    Vect_append_point(nPoints, mx, my, 0);
	}
    }

    if (looped) {
	Vect_append_point(nPoints, nPoints->x[0], nPoints->y[0],
			  nPoints->z[0]);
    }

    Vect_line_prune(nPoints);

    if (looped) {
	Vect_line_delete_point(Points, Points->n_points - 1);
    }
}