ObjectChange * polyconn_move_handle(PolyConn *poly, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { int handle_nr; handle_nr = get_handle_nr(poly, handle); switch(handle->id) { case HANDLE_MOVE_STARTPOINT: poly->points[0] = *to; break; case HANDLE_MOVE_ENDPOINT: poly->points[poly->numpoints-1] = *to; break; case HANDLE_CORNER: poly->points[handle_nr] = *to; break; default: g_warning("Internal error in polyconn_move_handle.\n"); break; } return NULL; }
/*! * \brief Return the major handle for the control point with the handle closest to * a given point. * @param bezier A bezier connection * @param point A point * @return The major (middle) handle of the bezier control that has the * handle closest to point. * @bug Don't we really want the major handle that's actually closest to * the point? This is used in connection with object menus and could cause * some unexpected selection of handles if a different segment has a control * point close to the major handle. */ Handle * bezierconn_closest_major_handle (BezierConn *bezier, Point *point) { Handle *closest = bezierconn_closest_handle(bezier, point); return bezier->object.handles[3*get_major_nr(get_handle_nr(bezier, closest))]; }
Handle * beziershape_closest_major_handle(BezierShape *bezier, Point *point) { Handle *closest = beziershape_closest_handle(bezier, point); int pos = get_major_nr(get_handle_nr(bezier, closest)); if (pos == 0) pos = bezier->numpoints - 1; return bezier->object.handles[3*pos - 1]; }
ObjectChange * beziershape_set_corner_type(BezierShape *bez, Handle *handle, BezCornerType corner_type) { Handle *mid_handle = NULL; Point old_left, old_right; int old_type; int handle_nr, comp_nr; handle_nr = get_handle_nr(bez, handle); switch (handle->id) { case HANDLE_BEZMAJOR: mid_handle = handle; break; case HANDLE_LEFTCTRL: handle_nr++; if (handle_nr == bez->object.num_handles) handle_nr = 0; mid_handle = bez->object.handles[handle_nr]; break; case HANDLE_RIGHTCTRL: handle_nr--; if (handle_nr < 0) handle_nr = bez->object.num_handles - 1; mid_handle = bez->object.handles[handle_nr]; break; default: g_assert_not_reached(); break; } comp_nr = get_major_nr(handle_nr); old_type = bez->corner_types[comp_nr]; old_left = bez->points[comp_nr].p2; if (comp_nr == bez->numpoints - 1) old_right = bez->points[1].p1; else old_right = bez->points[comp_nr+1].p1; #if 0 g_message("Setting corner type on segment %d to %s", comp_nr, corner_type == BEZ_CORNER_SYMMETRIC ? "symmetric" : corner_type == BEZ_CORNER_SMOOTH ? "smooth" : "cusp"); #endif bez->corner_types[comp_nr] = corner_type; if (comp_nr == 0) bez->corner_types[bez->numpoints-1] = corner_type; else if (comp_nr == bez->numpoints - 1) bez->corner_types[0] = corner_type; beziershape_straighten_corner(bez, comp_nr); return beziershape_create_corner_change(bez, mid_handle, &old_left, &old_right, old_type, corner_type); }
ObjectChange* polyshape_move_handle(PolyShape *poly, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { int handle_nr; handle_nr = get_handle_nr(poly, handle); poly->points[handle_nr] = *to; return NULL; }
/** Change the corner type of a bezier line. * @param bezier The bezierconn that has the corner * @param handle The handle whose corner should be set. * @param corner_type What type of corner the handle should have. * @returns Undo information about the corner change. */ ObjectChange * bezierconn_set_corner_type (BezierConn *bezier, Handle *handle, BezCornerType corner_type) { Handle *mid_handle; Point old_left, old_right; int old_type; int handle_nr, comp_nr; handle_nr = get_handle_nr(bezier, handle); switch (handle->id) { case HANDLE_BEZMAJOR: mid_handle = handle; break; case HANDLE_LEFTCTRL: handle_nr++; mid_handle = bezier->object.handles[handle_nr]; break; case HANDLE_RIGHTCTRL: handle_nr--; mid_handle = bezier->object.handles[handle_nr]; break; default: g_warning("Internal error: Setting corner type of endpoint of bezier"); return NULL; } comp_nr = get_major_nr(handle_nr); old_type = bezier->bezier.corner_types[comp_nr]; old_left = bezier->bezier.points[comp_nr].p2; old_right = bezier->bezier.points[comp_nr+1].p1; bezier->bezier.corner_types[comp_nr] = corner_type; bezierconn_straighten_corner(bezier, comp_nr); return bezierconn_create_corner_change(bezier, mid_handle, &old_left, &old_right, old_type, corner_type); }
void polyconn_move_handle(PolyConn *poly, Handle *handle, Point *to, HandleMoveReason reason) { int handle_nr; handle_nr = get_handle_nr(poly, handle); switch(handle->id) { case HANDLE_MOVE_STARTPOINT: poly->points[0] = *to; break; case HANDLE_MOVE_ENDPOINT: poly->points[poly->numpoints-1] = *to; break; case HANDLE_CORNER: poly->points[handle_nr] = *to; break; default: message_error("Internal error in polyconn_move_handle.\n"); break; } }
ObjectChange * beziershape_move_handle(BezierShape *bezier, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { int handle_nr, comp_nr, next_nr, prev_nr; Point delta, pt; delta = *to; point_sub(&delta, &handle->pos); handle_nr = get_handle_nr(bezier, handle); comp_nr = get_comp_nr(handle_nr); next_nr = comp_nr + 1; prev_nr = comp_nr - 1; if (comp_nr == bezier->numpoints - 1) next_nr = 1; if (comp_nr == 1) prev_nr = bezier->numpoints - 1; switch(handle->id) { case HANDLE_BEZMAJOR: if (comp_nr == bezier->numpoints - 1) { bezier->points[comp_nr].p3 = *to; bezier->points[0].p1 = bezier->points[0].p3 = *to; point_add(&bezier->points[comp_nr].p2, &delta); point_add(&bezier->points[1].p1, &delta); } else { bezier->points[comp_nr].p3 = *to; point_add(&bezier->points[comp_nr].p2, &delta); point_add(&bezier->points[comp_nr+1].p1, &delta); } break; case HANDLE_LEFTCTRL: bezier->points[comp_nr].p2 = *to; switch (bezier->corner_types[comp_nr]) { case BEZ_CORNER_SYMMETRIC: pt = bezier->points[comp_nr].p3; point_sub(&pt, &bezier->points[comp_nr].p2); point_add(&pt, &bezier->points[comp_nr].p3); bezier->points[next_nr].p1 = pt; break; case BEZ_CORNER_SMOOTH: { real len; pt = bezier->points[next_nr].p1; point_sub(&pt, &bezier->points[comp_nr].p3); len = point_len(&pt); pt = bezier->points[comp_nr].p3; point_sub(&pt, &bezier->points[comp_nr].p2); if (point_len(&pt) > 0) point_normalize(&pt); else { pt.x = 1.0; pt.y = 0.0; } point_scale(&pt, len); point_add(&pt, &bezier->points[comp_nr].p3); bezier->points[next_nr].p1 = pt; break; } case BEZ_CORNER_CUSP: /* no mirror point movement required */ break; } break; case HANDLE_RIGHTCTRL: bezier->points[comp_nr].p1 = *to; switch (bezier->corner_types[prev_nr]) { case BEZ_CORNER_SYMMETRIC: pt = bezier->points[prev_nr].p3; point_sub(&pt, &bezier->points[comp_nr].p1); point_add(&pt, &bezier->points[prev_nr].p3); bezier->points[prev_nr].p2 = pt; break; case BEZ_CORNER_SMOOTH: { real len; pt = bezier->points[prev_nr].p2; point_sub(&pt, &bezier->points[prev_nr].p3); len = point_len(&pt); pt = bezier->points[prev_nr].p3; point_sub(&pt, &bezier->points[comp_nr].p1); if (point_len(&pt) > 0) point_normalize(&pt); else { pt.x = 1.0; pt.y = 0.0; } point_scale(&pt, len); point_add(&pt, &bezier->points[prev_nr].p3); bezier->points[prev_nr].p2 = pt; break; } case BEZ_CORNER_CUSP: /* no mirror point movement required */ break; } break; default: message_error("Internal error in beziershape_move_handle."); break; } return NULL; }
/*! * \brief Move one of the handles associated with the * @param bezier The object whose handle is being moved. * @param handle The handle being moved. * @param to The position it has been moved to (corrected for * vertical/horizontal only movement). * @param cp If non-NULL, the connectionpoint found at this position. * If @a cp is NULL, there may or may not be a connectionpoint. * @param reason ignored * @param modifiers ignored * @return NULL * \memberof BezierConn */ ObjectChange* bezierconn_move_handle (BezierConn *bezier, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { int handle_nr, comp_nr; Point delta, pt; delta = *to; point_sub(&delta, &handle->pos); handle_nr = get_handle_nr(bezier, handle); comp_nr = get_comp_nr(handle_nr); switch(handle->id) { case HANDLE_MOVE_STARTPOINT: bezier->bezier.points[0].p1 = *to; /* shift adjacent point */ point_add(&bezier->bezier.points[1].p1, &delta); break; case HANDLE_MOVE_ENDPOINT: bezier->bezier.points[bezier->bezier.num_points-1].p3 = *to; /* shift adjacent point */ point_add(&bezier->bezier.points[bezier->bezier.num_points-1].p2, &delta); break; case HANDLE_BEZMAJOR: bezier->bezier.points[comp_nr].p3 = *to; /* shift adjacent point */ point_add(&bezier->bezier.points[comp_nr].p2, &delta); point_add(&bezier->bezier.points[comp_nr+1].p1, &delta); break; case HANDLE_LEFTCTRL: bezier->bezier.points[comp_nr].p2 = *to; if (comp_nr < bezier->bezier.num_points - 1) { switch (bezier->bezier.corner_types[comp_nr]) { case BEZ_CORNER_SYMMETRIC: pt = bezier->bezier.points[comp_nr].p3; point_sub(&pt, &bezier->bezier.points[comp_nr].p2); point_add(&pt, &bezier->bezier.points[comp_nr].p3); bezier->bezier.points[comp_nr+1].p1 = pt; break; case BEZ_CORNER_SMOOTH: { real len; pt = bezier->bezier.points[comp_nr+1].p1; point_sub(&pt, &bezier->bezier.points[comp_nr].p3); len = point_len(&pt); pt = bezier->bezier.points[comp_nr].p2; point_sub(&pt, &bezier->bezier.points[comp_nr].p3); if (point_len(&pt) > 0) point_normalize(&pt); else { pt.x = 1.0; pt.y = 0.0; } point_scale(&pt, -len); point_add(&pt, &bezier->bezier.points[comp_nr].p3); bezier->bezier.points[comp_nr+1].p1 = pt; break; } case BEZ_CORNER_CUSP: /* Do nothing to the other guy */ break; } } break; case HANDLE_RIGHTCTRL: bezier->bezier.points[comp_nr].p1 = *to; if (comp_nr > 1) { switch (bezier->bezier.corner_types[comp_nr-1]) { case BEZ_CORNER_SYMMETRIC: pt = bezier->bezier.points[comp_nr - 1].p3; point_sub(&pt, &bezier->bezier.points[comp_nr].p1); point_add(&pt, &bezier->bezier.points[comp_nr - 1].p3); bezier->bezier.points[comp_nr-1].p2 = pt; break; case BEZ_CORNER_SMOOTH: { real len; pt = bezier->bezier.points[comp_nr-1].p2; point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3); len = point_len(&pt); pt = bezier->bezier.points[comp_nr].p1; point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3); if (point_len(&pt) > 0) point_normalize(&pt); else { pt.x = 1.0; pt.y = 0.0; } point_scale(&pt, -len); point_add(&pt, &bezier->bezier.points[comp_nr-1].p3); bezier->bezier.points[comp_nr-1].p2 = pt; break; } case BEZ_CORNER_CUSP: /* Do nothing to the other guy */ break; } } break; default: g_warning("Internal error in bezierconn_move_handle.\n"); break; } return NULL; }