bool controls_contained_by_ends(const Cubic& c) { _Vector startTan = c[1] - c[0]; if (startTan.x == 0 && startTan.y == 0) { startTan = c[2] - c[0]; } _Vector endTan = c[2] - c[3]; if (endTan.x == 0 && endTan.y == 0) { endTan = c[1] - c[3]; } if (startTan.dot(endTan) >= 0) { return false; } _Line startEdge = {c[0], c[0]}; startEdge[1].x -= startTan.y; startEdge[1].y += startTan.x; _Line endEdge = {c[3], c[3]}; endEdge[1].x -= endTan.y; endEdge[1].y += endTan.x; double leftStart1 = is_left(startEdge, c[1]); if (leftStart1 * is_left(startEdge, c[2]) < 0) { return false; } double leftEnd1 = is_left(endEdge, c[1]); if (leftEnd1 * is_left(endEdge, c[2]) < 0) { return false; } return leftStart1 * leftEnd1 >= 0; }
//returns i < j bool angle_compare(Point2D pole, Point2D i, Point2D j) { if(pole == i) return 1; if(pole == j) return 0; if(is_left(pole, i , j) == 0) { if( (i.y > pole.y && j.y > pole.y) || (i.y < pole.y && j.y < pole.y) ) { return (get_length(i, pole) < get_length(j, pole)); } else if(i.y == pole.y && j.y == pole.y) { if( (i.x > pole.x && j.x > pole.x) || (i.x < pole.x && j.x < pole.y) ) return (get_length(i, pole) < get_length(j, pole)); else return (i.x < j.x); } else { return (i.y > j.y); } } else { if(is_left(pole, i, j) > 0) { if(i.y >= pole.y) return 1; else { if(j.y < pole.y) return 1; else return 0; } } else { if(i.y < pole.y) return 0; else { if(j.y >= pole.y) return 0; else return 1; } } } }
void delete_node(RB_tree *tree, short int key){ RB_node *node = get_node(tree, key); if(node != tree->nil){ RB_node *y, *x; if(node->left == tree->nil || node->right == tree->nil){ y = node; }else{ y = get_successor(node, tree->nil); } if(y->left != tree->nil){ x = y->left; }else{ x = y->right; } x->parent = y->parent; if(y->parent == tree->nil){ tree->root = x; }else if(is_left(y)){ y->parent->left = x; }else{ y->parent->right = x; } if(y != node){ node->key = y->key; } if(y->color == BLACK){ RB_delete_fixup(tree, x); } free(y); } }
static inline return_type starts_from_middle(side_info const& sides, coordinate_type const& dx1, coordinate_type const& dy1, S1 const& s1, S2 const& s2, char which, int how_a, int how_b) { // Calculate ARROW of b segment w.r.t. s1 coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1); coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1); int dir = is_left(dx1, dy1, dpx, dpy) ? 1 : -1; // From other perspective, then reverse bool const is_a = which == 'A'; if (is_a) { dir = -dir; } return return_type(sides, 's', how_a, how_b, is_a ? dir : -dir, ! is_a ? dir : -dir); }
/*** ConvexHull::find_positive * May return any number n where the segment n -> n + 1 (possibly looped around) in the hull such * that the point is on the wrong side to be within the hull. Returns -1 if it is within the hull.*/ int ConvexHull::find_left(Point p) { int l = boundary.size(); //Who knows if C++ is smart enough to optimize this? for(int i = 0; i < l; i++) { if(is_left(p, i)) return i; } return -1; }
//deleting not sorted useless points std::vector<Point2D> delete_chain(std::vector<Point2D> points, Point2Df pole) { //find most right and most left; int left = 0; int right = 0; double enext; points.push_back(points[0]); double eprev = is_left((Point2Df)points[0],(Point2Df) points[1], pole); for(int i = 1; i < points.size() - 1; i++) { enext = is_left((Point2Df)points[i], (Point2Df)points[i + 1], pole); if ((eprev <= 0.0) && (enext > 0.0)) { if (is_left(pole, (Point2Df)points[i], (Point2Df)points[right]) >= 0.0) right = i; } else if ((eprev > 0) && (enext <= 0)) { if (is_left(pole, (Point2Df)points[i], (Point2Df)points[left]) <= 0.0) left = i; } eprev = enext; if(i == points.size() - 1) break; } points.pop_back(); //angle_compare_180 std::vector<Point2D> sset; if (right < left) { sset.assign(points.begin() + right, points.begin() + left + 1); return sset; } else { points.erase(points.begin() + left + 1, points.begin() + right); return points; } }
static void pointFinder(const Quadratic& q1, const Quadratic& q2) { for (int index = 0; index < 3; ++index) { double t = nearestT(q1, q2[index]); _Point onQuad; xy_at_t(q1, t, onQuad.x, onQuad.y); SkDebugf("%s t=%1.9g (%1.9g,%1.9g) dist=%1.9g\n", __FUNCTION__, t, onQuad.x, onQuad.y, onQuad.distance(q2[index])); double left[3]; left[0] = is_left((const _Line&) q1[0], q2[index]); left[1] = is_left((const _Line&) q1[1], q2[index]); _Line diag = {q1[0], q1[2]}; left[2] = is_left(diag, q2[index]); SkDebugf("%s left=(%d, %d, %d) inHull=%s\n", __FUNCTION__, floatSign(left[0]), floatSign(left[1]), floatSign(left[2]), point_in_hull(q1, q2[index]) ? "true" : "false"); } SkDebugf("\n"); }
int in_polygon(std::vector<Point2D> polygon, Point2Df p) { for(int i = 0; i < polygon.size() - 1; i++) { if(is_left( (Point2Df) polygon[i],(Point2Df) polygon[i + 1], p) < 0.0) return 0; } return 1; }
void RB_delete_fixup(RB_tree *tree, RB_node *node){ RB_node *sibl; while(node != tree->root && node->color == BLACK){ if(is_left(node)){ sibl = node->parent->right; if(sibl->color == RED){//1st CASE sibl->color = BLACK; sibl->parent->color = RED; rotate_left(tree, node->parent); sibl = node->parent->right; } if(sibl->left->color == BLACK && sibl->right->color == BLACK){ //2nd CASE sibl->color = RED; node = node->parent; }else{ if(sibl->right->color == BLACK){//3th CASE --> 4th sibl->left->color = BLACK; sibl->color = RED; rotate_right(tree, sibl); sibl = node->parent->right; } sibl->color = node->parent->color;//4th CASE node->parent->color = BLACK; sibl->right->color = BLACK; rotate_left(tree, node->parent); node = tree->root; } }else{ sibl = node->parent->left; if(sibl->color == RED){//1st CASE sibl->color = BLACK; sibl->parent->color = RED; rotate_right(tree, node->parent); sibl = node->parent->left; } if(sibl->left->color == BLACK && sibl->right->color == BLACK){//2nd CASE sibl->color = RED; node = node->parent; }else{ if(sibl->left->color == BLACK){//3th CASE --> 4th sibl->right->color = BLACK; sibl->color = RED; rotate_left(tree, sibl); sibl = node->parent->left; } sibl->color = node->parent->color;//4th CASE node->parent->color = BLACK; sibl->left->color = BLACK; rotate_right(tree, node->parent); node = tree->root; } } } node->color = BLACK; }
std::vector<Point2D> graham_scan(std::vector<Point2D> points, Point2D pole) { std::vector<Point2D> st; points.push_back(pole); if(is_line(points)) { st.push_back(points[points.size() - 1]); st.push_back(points[points.size() - 2]); return st; } points.pop_back(); st.push_back(points[points.size() - 1]); st.push_back(pole); for(int i = 0; i < points.size(); i++) { long long int left = is_left(st[st.size() - 2], st[st.size() - 1], points[i] ); if( left > 0) { if(!(points[i] == st[0]) && !(points[i] == st[1])) st.push_back(points[i]); } else { st.pop_back(); i--; } } //test of 3 last points on one line if(is_left(st[st.size() - 2], st[st.size() - 1], points[points.size() - 1]) == 0) { st.pop_back(); } return st; }
static inline return_type b_ends_at_middle(side_info const& sides, coordinate_type const& dx, coordinate_type const& dy, S1 const& s1, S2 const& s2) { coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2); coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2); return is_left(dx, dy, dpx, dpy) ? return_type(sides, 'm', 0, 1, 1, 1) : return_type(sides, 'm', 0, 1, -1, -1); }
int scan(FILE *target) { hash_t *var_map = malloc(sizeof(hash_t)); hash_init(var_map, 1024); write_header(target); int ret = 0; while(next() == true){ if(is_alpha() == false){ printf("An instruction can only start with a function call or assignment\n"); return 1; } char *current_token = get_token(); char *temp; strcpy(temp, current_token); if(next() == false){ printf("Incomplete instruction\n"); return 1; } if(is_left()){ ret = parse_call(target, temp, var_map); /* It is a call */ } else if(is_assignment()){ ret = parse_assignment(target, temp, var_map); /* It is an assignment */ } else { printf("Not a valid instruction\n"); return 1; } if(ret == 1 ){ printf("Syntax error\n"); return 1; } } write_end(target); free(var_map); return ret; }
static inline return_type angle(side_info const& sides, coordinate_type const& dx1, coordinate_type const& dy1, S1 const& s1, S2 const& s2, char how, int how_a, int how_b) { coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1); coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1); return is_left(dx1, dy1, dpx, dpy) ? return_type(sides, how, how_a, how_b, 1, 1) : return_type(sides, how, how_a, how_b, -1, -1); }
void SimplePolylineConvex::push_point(PointD const& p) { if (vertices_.size() < 2 || is_left(*(vertices_.end() - 2), *(vertices_.end() - 1), p)) vertices_.push_back(p); else { // the middle point (the last one currently in vertices_) is not convex // remove it and check again the last three points vertices_.pop_back(); push_point(p); } }
// To be harmonized static inline return_type a_ends_at_middle(side_info const& sides, coordinate_type const& dx, coordinate_type const& dy, S1 const& s1, S2 const& s2) { coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1); coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1); // Ending at the middle, one ARRIVES, the other one is NEUTRAL // (because it both "arrives" and "departs" there return is_left(dx, dy, dpx, dpy) ? return_type(sides, 'm', 1, 0, 1, 1) : return_type(sides, 'm', 1, 0, -1, -1); }
bool is_line(std::vector<Point2D> points) { if(points.size() < 3) { //printf("2 points"); return true; } for(int i = 0; i < points.size() - 2; i++) { if(is_left(points[i], points[i + 1], points[i + 2]) != 0) return false; } return true; }
//takes sorted points std::vector<Point2D> graham_scan(std::vector<Point2D> points) { std::vector<Point2D> st; if(is_line(points)) { st.push_back(points[0]); st.push_back(points[points.size() - 1]); return st; } Point2D rightest = points[0]; int rightest_pos = 0; for(int i = 0; i < points.size(); i++) { if(points[i].x > rightest.x || (points[i].x == rightest.x && points[i].y < rightest.y)) { rightest = points[i]; rightest_pos = i; } } int cur = 1; st.push_back(points[get_index(rightest_pos - 1, points.size())]); st.push_back(points[rightest_pos]); while(!(st[1] == st[st.size() - 1] && st.size() > 2)) { long long int left = is_left(st[st.size() - 2], st[st.size() - 1], points[get_index(cur + rightest_pos, points.size())]); if( left > 0) { st.push_back(points[get_index(cur + rightest_pos, points.size())]); cur++; } else { st.pop_back(); //cur--; } } st.erase(st.begin()); st.pop_back(); return st; }
void rotate_right(RB_tree *tree, RB_node *node){ RB_node *temp = node->left; if(node->left != tree->nil){ node->left = temp->right; temp->right = node; node->left->parent = node; if(node->parent == tree->nil){ tree->root = temp; }else{ if(is_left(node)){ node->parent->left = temp; }else{ node->parent->right = temp; } } temp->parent = node->parent; node->parent = temp; } }
void RB_insert_fixup(RB_tree *tree, RB_node *node){ node->color = RED; RB_node *last; while(node != tree->root && node->parent->color == RED){ if(is_left(node->parent)){ last = node->parent->parent->right; if(last->color == RED){//1st CASE node->parent->color = BLACK; last->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; }else{ if(node == node->parent->right){//2nd CASE --> 3rd node = node->parent; rotate_left(tree, node); } node->parent->color = BLACK;//3rd CASE node->parent->parent->color = RED; rotate_right(tree, node->parent->parent); } }else{ last = node->parent->parent->left; if(last->color == RED){//1st CASE node->parent->color = BLACK; last->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; }else{ if(node == node->parent->left){//2nd CASE --> 3rd node = node->parent; rotate_right(tree, node); } node->parent->color = BLACK;//3rd CASE node->parent->parent->color = RED; rotate_left(tree, node->parent->parent); } } } }
// Partition the given triangles into two groups: those (mostly) left of // and mostly right of the given split plane, based on a triangle's // bound for the given split axis. Sets the parameters num_triangles_left // and num_triangles_right when done. static void partition_on_split_value(int *num_triangles_left, int *num_triangles_right, triangle *first_triangle, int num_triangles, int split_axis, float split_value) { triangle *l, *r, t; triangle *last_triangle; last_triangle = first_triangle + num_triangles - 1; l = first_triangle; r = last_triangle; while (l < r) { // Increase "l" to first triangle that needs to be on the *right* (yes, right) while (l <= last_triangle && is_left(l, split_axis, split_value)) l++; // Decrease "r" to first triangle that needs to be on the *left* while (r >= first_triangle && !is_left(r, split_axis, split_value)) r--; if (l < r) { // Swap triangles to put them in the correct lists t = *l; *l = *r; *r = t; // Update pointers as we have now processed 2 triangles l++; r--; } } // When we get here, l >= r if (l > last_triangle) { // All triangles on the left of the split plane *num_triangles_left = num_triangles; *num_triangles_right = 0; } else if (r < first_triangle) { // All triangles on the right *num_triangles_left = 0; *num_triangles_right = num_triangles; } else { // Triangles on both sides of the split plane *num_triangles_left = l - first_triangle; *num_triangles_right = num_triangles - *num_triangles_left; if (l == r) { // The triangle pointed to by both l and r hasn't been processed yet if (is_left(l, split_value, split_axis)) { // Correct the triangle count in this case, as we included // the triangle on the right initially, while it is actually // on the left of the split plane // *num_triangles_left++; // *num_triangles_right--; } } } }
/** * A.M. Andrew's monotone chain 2D convex hull algorithm * * \param points An array of 2D points presorted by increasing x and y-coords. * \param n The number of points in points. * \param r_points An array of the convex hull vertex indices (max is n). * \returns the number of points in r_points. */ int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[]) { /* the output array r_points[] will be used as the stack */ int bot = 0; int top = -1; /* indices for bottom and top of the stack */ int i; /* array scan index */ int minmin, minmax; int maxmin, maxmax; float xmax; /* Get the indices of points with min x-coord and min|max y-coord */ float xmin = points[0][0]; for (i = 1; i < n; i++) { if (points[i][0] != xmin) { break; } } minmin = 0; minmax = i - 1; if (minmax == n - 1) { /* degenerate case: all x-coords == xmin */ r_points[++top] = minmin; if (points[minmax][1] != points[minmin][1]) /* a nontrivial segment */ r_points[++top] = minmax; r_points[++top] = minmin; /* add polygon endpoint */ return top + 1; } /* Get the indices of points with max x-coord and min|max y-coord */ maxmax = n - 1; xmax = points[n - 1][0]; for (i = n - 2; i >= 0; i--) { if (points[i][0] != xmax) { break; } } maxmin = i + 1; /* Compute the lower hull on the stack r_points */ r_points[++top] = minmin; /* push minmin point onto stack */ i = minmax; while (++i <= maxmin) { /* the lower line joins points[minmin] with points[maxmin] */ if (is_left(points[minmin], points[maxmin], points[i]) >= 0 && i < maxmin) { continue; /* ignore points[i] above or on the lower line */ } while (top > 0) { /* there are at least 2 points on the stack */ /* test if points[i] is left of the line at the stack top */ if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { break; /* points[i] is a new hull vertex */ } else { top--; /* pop top point off stack */ } } r_points[++top] = i; /* push points[i] onto stack */ } /* Next, compute the upper hull on the stack r_points above the bottom hull */ if (maxmax != maxmin) { /* if distinct xmax points */ r_points[++top] = maxmax; /* push maxmax point onto stack */ } bot = top; /* the bottom point of the upper hull stack */ i = maxmin; while (--i >= minmax) { /* the upper line joins points[maxmax] with points[minmax] */ if (is_left(points[maxmax], points[minmax], points[i]) >= 0 && i > minmax) { continue; /* ignore points[i] below or on the upper line */ } while (top > bot) { /* at least 2 points on the upper stack */ /* test if points[i] is left of the line at the stack top */ if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) { break; /* points[i] is a new hull vertex */ } else { top--; /* pop top point off stack */ } } if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) { return top + 1; /* special case (mgomes) */ } r_points[++top] = i; /* push points[i] onto stack */ } if (minmax != minmin) { r_points[++top] = minmin; /* push joining endpoint onto stack */ } return top + 1; }
//merging of 2 convex hulls std::vector<Point2D> merge(std::vector<Point2D> set1, std::vector<Point2D> set2) { Point2Df p; std::vector<Point2D> sum; int is_line1 = is_line(set1); int is_line2 = is_line(set2); if(!is_line1) { for(int i = 0; i < set1.size() - 2; i++) { if(is_left(set1[i], set1[i + 1], set1[i + 2]) != 0) { p = centroid(set1[i], set1[i + 1], set1[i + 2]); break; } } } else if(!is_line2) { for(int i = 0; i < set2.size() - 2; i++) { if(is_left(set2[i], set2[i + 1], set2[i + 2]) != 0) { p = centroid(set2[i], set2[i + 1], set2[i + 2]); break; } } } if(!is_line1 && !is_line2)// 2 polygons { if(in_polygon(set2, p) != 0) { sum = merge_polygons(set1, set2, p); return graham_scan(sum); } else { std::vector<Point2D> clean_set2; clean_set2 = delete_chain(set2, p); sum = merge_polygons(set1, clean_set2, p); return graham_scan(sum); } } else if (!is_line1 && is_line2)//polygon with centroid p and line { std::vector<Point2D> clean_set2; /* clean_set2 = delete_chain(set2, p); sum = merge_polygons(set1, clean_set2, p); */ if(angle_compare(p, (Point2Df)set2[0], (Point2Df)set2[set2.size() - 1])) { clean_set2.push_back(set2[0]); clean_set2.push_back(set2[set2.size() - 1]); } else { clean_set2.push_back(set2[set2.size() - 1]); clean_set2.push_back(set2[0]); } sum = merge_polygons(set1, clean_set2, p); return graham_scan(sum); } else if(is_line1 && !is_line2) { std::vector<Point2D> clean_set1; /* clean_set1 = delete_chain(set1, p); sum = merge_polygons(clean_set1, set2, p); */ if(angle_compare(p, (Point2Df)set1[0], (Point2Df)set1[set1.size() - 1])) { clean_set1.push_back(set1[0]); clean_set1.push_back(set1[set1.size() - 1]); } else { clean_set1.push_back(set1[set1.size() - 1]); clean_set1.push_back(set1[0]); } sum = merge_polygons(clean_set1, set2, p); return graham_scan(sum); } else // if(is_line1 && is_line2) { std::vector<Point2D> clean_set1; clean_set1.push_back(set1[0]); clean_set1.push_back(set1[set1.size() - 1]); clean_set1.push_back(set2[0]); clean_set1.push_back(set2[set2.size() - 1]); return get_hull(clean_set1); } }