void wxGL_PMFCanvas::ray_pick(vector3d point, vector3d norm){ int idx1=-1; int idx2=-1; float max_dist = FLT_MAX; for(unsigned int i = 0; i<omni.point.size(); i++){ for(unsigned int j = 0; j< omni.point[i].size(); j++){ float d = point_line_distance(omni.point[i][j].pos+model.get_model_offset(omni.point[i][j].model), point, norm); float rad = 0.0f; if(omni.flags & OMNIPOINT_ANY_PATH)//paths can have rediculusly huge radius's rad = log(omni.point[i][j].rad)+1.0f; else rad = omni.point[i][j].rad; if(d < rad && d<max_dist){ max_dist = d; idx1 = i; idx2 = j; } } } if(idx1 >-1 && idx2 >-1){ set_selected_omni_points(idx1, idx2); wxCommandEvent commandEvent(OMNIPOINT_RAY_PICKED, GetId()); GetEventHandler()->ProcessEvent(commandEvent); Render(); } }
static void normal_form (gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble * nx, gdouble * ny, gdouble * d) { gdouble l; *nx = by - ay; *ny = ax - bx; l = length (*nx, *ny); *nx /= l; *ny /= l; *d = point_line_distance (ax, ay, *nx, *ny); }
inline void ramer_douglas_peucker_algorithm(const Polyline& poly, Polyline& nPoly, std::size_t start, std::size_t end, const Length& epsilon) { using access = point_sequence_traits<Polyline>; using point_t = typename access::point_type; using length_t = typename geometric_traits<point_t>::arithmetic_type; using dimensionless_t = typename geometric_traits<point_t>::dimensionless_type; using vector_t = vector<dimensionless_t, dimension_of<point_t>::value>; using line_t = line<point_t, vector_t>; // Find the point with the maximum distance auto dmax = constants::zero<length_t>(); boost::optional<std::size_t> index; if ((start + 2) < end) { line_t l(access::get_point(poly, start), access::get_point(poly, end - 1)); for (std::size_t i = start + 1; (i + 1) < end; ++i) { auto d = point_line_distance(access::get_point(poly, i), l); if (d > dmax) { index = i; dmax = d; } } } // If max distance is greater than epsilon, recursively simplify if (dmax > epsilon) { GEOMETRIX_ASSERT(index); ramer_douglas_peucker_algorithm(poly, nPoly, start, *index, epsilon); access::pop_back(nPoly); ramer_douglas_peucker_algorithm(poly, nPoly, *index, end, epsilon); } else { GEOMETRIX_ASSERT((start + 1) != end); access::push_back(nPoly, access::get_point(poly,start)); access::push_back(nPoly, access::get_point(poly, end-1)); } }
// point_line_distance double point_line_distance(BPoint point, BPoint pa, BPoint pb) { // first figure out if point is between segment start and end points double a = point_point_distance(point, pb); double b = point_point_distance(point, pa); double c = point_point_distance(pa, pb); float currentDist = min_c(a, b); if (a > 0.0 && b > 0.0) { double alpha = acos((b*b + c*c - a*a) / (2*b*c)); double beta = acos((a*a + c*c - b*b) / (2*a*c)); if (alpha <= M_PI_2 && beta <= M_PI_2) { currentDist = fabs(point_line_distance(pa.x, pa.y, pb.x, pb.y, point.x, point.y)); } } return currentDist; }
// calc_angle double calc_angle(BPoint origin, BPoint from, BPoint to, bool degree) { double angle = 0.0; double d = point_line_distance(from.x, from.y, origin.x, origin.y, to.x, to.y); if (d != 0.0) { double a = point_point_distance(from, to); double b = point_point_distance(from, origin); double c = point_point_distance(to, origin); if (a > 0.0 && b > 0.0 && c > 0.0) { angle = acos((b*b + c*c - a*a) / (2.0*b*c)); if (d < 0.0) angle = -angle; if (degree) angle = angle * 180.0 / M_PI; } } return angle; }
/* draw an angle from the current point to b and then to c, * with a rounded corner of the given radius. */ static void rounded_corner (cairo_t * cr, gdouble bx, gdouble by, gdouble cx, gdouble cy, gdouble radius) { gdouble ax, ay; gdouble n1x, n1y, d1; gdouble n2x, n2y, d2; gdouble pd1, pd2; gdouble ix, iy; gdouble dist1, dist2; gdouble nx, ny, d; gdouble a1x, a1y, c1x, c1y; gdouble phi1, phi2; cairo_get_current_point (cr, &ax, &ay); #ifdef KBDRAW_DEBUG printf (" current point: (%f, %f), radius %f:\n", ax, ay, radius); #endif /* make sure radius is not too large */ dist1 = length (bx - ax, by - ay); dist2 = length (cx - bx, cy - by); radius = MIN (radius, MIN (dist1, dist2)); /* construct normal forms of the lines */ normal_form (ax, ay, bx, by, &n1x, &n1y, &d1); normal_form (bx, by, cx, cy, &n2x, &n2y, &d2); /* find which side of the line a,b the point c is on */ if (point_line_distance (cx, cy, n1x, n1y) < d1) pd1 = d1 - radius; else pd1 = d1 + radius; /* find which side of the line b,c the point a is on */ if (point_line_distance (ax, ay, n2x, n2y) < d2) pd2 = d2 - radius; else pd2 = d2 + radius; /* intersect the parallels to find the center of the arc */ intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy); nx = (bx - ax) / dist1; ny = (by - ay) / dist1; d = point_line_distance (ix, iy, nx, ny); /* a1 is the point on the line a-b where the arc starts */ intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y); nx = (cx - bx) / dist2; ny = (cy - by) / dist2; d = point_line_distance (ix, iy, nx, ny); /* c1 is the point on the line b-c where the arc ends */ intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y); /* determine the first angle */ if (a1x - ix == 0) phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2; else if (a1x - ix > 0) phi1 = atan ((a1y - iy) / (a1x - ix)); else phi1 = M_PI + atan ((a1y - iy) / (a1x - ix)); /* determine the second angle */ if (c1x - ix == 0) phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2; else if (c1x - ix > 0) phi2 = atan ((c1y - iy) / (c1x - ix)); else phi2 = M_PI + atan ((c1y - iy) / (c1x - ix)); /* compute the difference between phi2 and phi1 mod 2pi */ d = phi2 - phi1; while (d < 0) d += 2 * M_PI; while (d > 2 * M_PI) d -= 2 * M_PI; #ifdef KBDRAW_DEBUG printf (" line 1 to: (%f, %f):\n", a1x, a1y); #endif if (!(isnan (a1x) || isnan (a1y))) cairo_line_to (cr, a1x, a1y); /* pick the short arc from phi1 to phi2 */ if (d < M_PI) cairo_arc (cr, ix, iy, radius, phi1, phi2); else cairo_arc_negative (cr, ix, iy, radius, phi1, phi2); #ifdef KBDRAW_DEBUG printf (" line 2 to: (%f, %f):\n", cx, cy); #endif cairo_line_to (cr, cx, cy); }