/* if cross is not NULL, it will be incremented for each ray crossing */ static real bez_point_distance_and_ray_crosses(const Point *b1, const Point *b2, const Point *b3, const Point *b4, real line_width, const Point *point, guint *cross) { static gboolean calculated_coeff = FALSE; static real coeff[NBEZ_SEGS+1][4]; int i; real line_dist = G_MAXFLOAT; Point prev, pt; if (!calculated_coeff) { for (i = 0; i <= NBEZ_SEGS; i++) { real t1 = ((real)i)/NBEZ_SEGS, t2 = t1*t1, t3 = t1*t2; real it1 = 1-t1, it2 = it1*it1, it3 = it1*it2; coeff[i][0] = it3; coeff[i][1] = 3 * t1 * it2; coeff[i][2] = 3 * t2 * it1; coeff[i][3] = t3; } } calculated_coeff = TRUE; prev.x = coeff[0][0] * b1->x + coeff[0][1] * b2->x + coeff[0][2] * b3->x + coeff[0][3] * b4->x; prev.y = coeff[0][0] * b1->y + coeff[0][1] * b2->y + coeff[0][2] * b3->y + coeff[0][3] * b4->y; for (i = 1; i <= NBEZ_SEGS; i++) { real dist; pt.x = coeff[i][0] * b1->x + coeff[i][1] * b2->x + coeff[i][2] * b3->x + coeff[i][3] * b4->x; pt.y = coeff[i][0] * b1->y + coeff[i][1] * b2->y + coeff[i][2] * b3->y + coeff[i][3] * b4->y; dist = distance_line_point(&prev, &pt, line_width, point); line_dist = MIN(line_dist, dist); if (cross) *cross += line_crosses_ray(&prev, &pt, point); prev = pt; } return line_dist; }
real distance_bez_shape_point(const BezPoint *b, guint npoints, real line_width, const Point *point) { Point last; guint i; real line_dist = G_MAXFLOAT; guint crossings = 0; g_return_val_if_fail(b[0].type == BEZ_MOVE_TO, -1); last = b[0].p1; for (i = 1; i < npoints; i++) { real dist; switch (b[i].type) { case BEZ_MOVE_TO: /* no complains, there are renderers capable to handle this */ last = b[i].p1; break; case BEZ_LINE_TO: dist = distance_line_point(&last, &b[i].p1, line_width, point); crossings += line_crosses_ray(&last, &b[i].p1, point); line_dist = MIN(line_dist, dist); last = b[i].p1; break; case BEZ_CURVE_TO: dist = bez_point_distance_and_ray_crosses(&last, &b[i].p1, &b[i].p2, &b[i].p3, line_width, point, &crossings); line_dist = MIN(line_dist, dist); last = b[i].p3; break; } } /* If there is an odd number of ray crossings, we are inside the polygon. * Otherwise, return the minium distance from a line segment */ if (crossings % 2 == 1) return 0.0; else return line_dist; }
real distance_polygon_point(const Point *poly, guint npoints, real line_width, const Point *point) { guint i, last = npoints - 1; real line_dist = G_MAXFLOAT; guint crossings = 0; /* calculate ray crossings and line distances */ for (i = 0; i < npoints; i++) { real dist; crossings += line_crosses_ray(&poly[last], &poly[i], point); dist = distance_line_point(&poly[last], &poly[i], line_width, point); line_dist = MIN(line_dist, dist); last = i; } /* If there is an odd number of ray crossings, we are inside the polygon. * Otherwise, return the minium distance from a line segment */ if (crossings % 2 == 1) return 0.0; else return line_dist; }
double distance_polygon_point(const Point *poly, int npoints, double lineWidth, const Point *point) { int i, last = npoints - 1; // double line_dist = G_MAXFLOAT; double line_dist = 1.0; int crossings = 0; for (i = 0; i < npoints; i++) { double dist; crossings += line_crosses_ray(&poly[last], &poly[i], point); dist = distance_line_point(&poly[last], &poly[i], lineWidth, point); line_dist = qMin(line_dist, dist); last = i; } if (crossings % 2 == 1) return 0.0; else return line_dist; }