int main() {
  point p, q;

  assert(line_intersection(-1, 1, 0, 1, 1, -3, &p) == 0);
  assert(EQP(p, point(1.5, 1.5)));
  assert(line_intersection(point(0, 0), point(1, 1), point(0, 4), point(4, 0),
                           &p) == 0);
  assert(EQP(p, point(2, 2)));

  {
    #define test(a, b, c, d, e, f, g, h) seg_intersection( \
        point(a, b), point(c, d), point(e, f), point(g, h), &p, &q)

    // Intersection is a point.
    assert(0 == test(-4, 0, 4, 0, 0, -4, 0, 4) && EQP(p, point(0, 0)));
    assert(0 == test(0, 0, 10, 10, 2, 2, 16, 4) && EQP(p, point(2, 2)));
    assert(0 == test(-2, 2, -2, -2, -2, 0, 0, 0) && EQP(p, point(-2, 0)));
    assert(0 == test(0, 4, 4, 4, 4, 0, 4, 8) && EQP(p, point(4, 4)));

    // Intersection is a segment.
    assert(1 == test(10, 10, 0, 0, 2, 2, 6, 6));
    assert(EQP(p, point(2, 2)) && EQP(q, point(6, 6)));
    assert(1 == test(6, 8, 14, -2, 14, -2, 6, 8));
    assert(EQP(p, point(6, 8)) && EQP(q, point(14, -2)));

    // No intersection.
    assert(-1 == test(6, 8, 8, 10, 12, 12, 4, 4));
    assert(-1 == test(-4, 2, -8, 8, 0, 0, -4, 6));
    assert(-1 == test(4, 4, 4, 6, 0, 2, 0, 0));
    assert(-1 == test(4, 4, 6, 4, 0, 2, 0, 0));
    assert(-1 == test(-2, -2, 4, 4, 10, 10, 6, 6));
    assert(-1 == test(0, 0, 2, 2, 4, 0, 1, 4));
    assert(-1 == test(2, 2, 2, 8, 4, 4, 6, 4));
    assert(-1 == test(4, 2, 4, 4, 0, 8, 10, 0));
  }

  assert(EQP(point(2.5, 2.5), closest_point(-1, -1, 5, point(0, 0))));
  assert(EQP(point(3, 0), closest_point(1, 0, -3, point(0, 0))));
  assert(EQP(point(0, 3), closest_point(0, 1, -3, point(0, 0))));

  assert(EQP(point(3, 0),
             closest_point(point(3, 0), point(3, 3), point(0, 0))));
  assert(EQP(point(2, -1),
             closest_point(point(2, -1), point(4, -1), point(0, 0))));
  assert(EQP(point(4, -1),
             closest_point(point(2, -1), point(4, -1), point(5, 0))));
  return 0;
}
예제 #2
0
int do_fraction (struct Plex *plex, struct PlexEdge *plexedg, double *p1, double *p2, double *p3, double *p4)
{
	int k;
	double fraction;
	struct PlexVertex *newvtx;
	struct PlexEdge *newedg;
	char message[MAXLINE];

	if (plex -> n_vertex >= plex -> maxvertex) {
		set_error1 ("too many vertices");
		return (0);
	}
	if (plex -> n_edge >= plex -> maxedge) {
		sprintf (message, "do_fraction: too many edges (%6ld)",
			plex -> maxedge);
		set_error1 (message);
		return (0);
	}
	fraction =  line_intersection (p1, p2, p3, p4);
	/* new vertex */
	newvtx = plex -> plexvertices + plex -> n_vertex;
	for (k = 0; k < 3; k++)
		newvtx -> center[k] = (1.0 - fraction) * *(p1 + k) + fraction * *(p2 + k);
	newvtx -> type = PolyVertex;
	plex -> n_vertex++;
	/* new edge */
	newedg = plex -> plexedges + plex -> n_edge;
	newedg -> vns[0] = plex -> n_vertex;
	newedg -> vns[1] = plexedg -> vns[1];
	plexedg -> vns[1] = plex -> n_vertex;
	plex -> n_edge++;
	plex -> n_cut++;
	return (1);
}
예제 #3
0
bool ray_crosses_segment(segment *s, ray *r, point *intersect) {
  if(line_intersection(s->a.x, s->a.y, s->b.x, s->b.y, 
          r->center.x, r->center.y, r->out.x, r->out.y, intersect)) {
    if(is_intersect_in_ray(r, intersect) && is_intersect_in_segment(s, intersect)) {
      return true;
    }
  }
  return false;
}
point closest_point(double a, double b, double c, const point &p) {
  if (EQ(a, 0)) {
    return point(p.x, -c);  // Horizontal line.
  }
  if (EQ(b, 0)) {
    return point(-c, p.y);  // Vertical line.
  }
  point res;
  line_intersection(a, b, c, -b, a, b*p.x - a*p.y, &res);
  return res;
}
예제 #5
0
파일: aabr.cpp 프로젝트: laerne/bOoM
bool aabr_smallest_subaabr_containing_line (aabr const& r, move2 const& line, aabr& res__aabr)
{
	real2 p1,p2;
	real unused, thouShaltNotPass;
	if(   line_intersection(r, line, p1, unused, p2, thouShaltNotPass)   )
	{
		real2 bottom_left( MIN(p1.x,p2.x), MIN(p1.y,p2.y));
		real2 top_right( MAX(p1.x,p2.x), MAX(p1.y,p2.y));
		res__aabr = aabr( bottom_left, top_right - bottom_left );
		return true;
	}
	else
	  return false;
}
예제 #6
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 );
}
예제 #7
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);
    }
}
예제 #8
0
파일: light.cpp 프로젝트: netguy204/giggle
// returns true if further calls could possibly result in a mesh
void LightCaster::add_triangle(Mesh* result, const Vector_& light,
                               Wall* last_closest, float beginAngle, float nextAngle) {
  // within our angle bounds?
  float da1 = signed_angular_distance(angle, beginAngle);
  if(da1 > halfwidth) return; // swath begins after our cutoff
  float da2 = signed_angular_distance(angle, nextAngle);
  if(da2 < -halfwidth) return; // swath ends before our cutoff

  // clamp the values we did get
  float ada1 = ABS(da1);
  if(ada1 > halfwidth) {
    float fixup = halfwidth - ada1;
    beginAngle += fixup * sign(da1);
  }

  float ada2 = ABS(da2);
  if(ada2 > halfwidth) {
    float fixup = halfwidth - ada2;
    nextAngle += fixup * sign(da2);
  }


  int steps = ceilf(signed_angular_distance(beginAngle, nextAngle) / max_angle_step);

  float oldBegin = beginAngle;
  float oldNext = nextAngle;

  for(int ii = 0; ii < steps; ++ii) {
    beginAngle = oldBegin + ii * max_angle_step;
    float delta = signed_angular_distance(beginAngle, oldNext);
    nextAngle = beginAngle + MIN(delta, max_angle_step);

    // interset the discovered angle range with the previously
    // closest wall segment
    Vector_ a1;
    a1.x = light.x + cosf(beginAngle);
    a1.y = light.y + sinf(beginAngle);
    Vector_ a2;
    a2.x = light.x + cosf(nextAngle);
    a2.y = light.y + sinf(nextAngle);
    Vector_ i1, i2;
    line_intersection(&i1, &last_closest->start, &last_closest->end, &light, &a1);
    line_intersection(&i2, &last_closest->start, &last_closest->end, &light, &a2);

    Color c1, c2;
    float d1 = vector_dist(&i1, &light);
    float d2 = vector_dist(&i2, &light);
    color_lerp(&c1, &min_color, &max_color, MIN(1.0f, d1 / max_range));
    color_lerp(&c2, &min_color, &max_color, MIN(1.0f, d2 / max_range));

    if(d1 > max_range) {
      vector_direction_scaled(&i1, &i1, &light, max_range);
      vector_add(&i1, &i1, &light);
    }

    if(d2 > max_range) {
      vector_direction_scaled(&i2, &i2, &light, max_range);
      vector_add(&i2, &i2, &light);
    }

    // add a triangle to the mesh
    result->add_point(light, min_color);
    result->add_point(i1, c1);
    result->add_point(i2, c2);
  }
}