Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 7509) +++ trunk/scconfig/Rev.h (revision 7510) @@ -1 +1 @@ -static const int myrev = 7439; +static const int myrev = 7509; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 7509) +++ trunk/scconfig/Rev.tab (revision 7510) @@ -1,3 +1,4 @@ +7509 configure rubber band upgrade, new go code 7439 configure tEDAx chnaged from import to io 7432 configure mentor_sch plugin upgrades 7372 configure gtk splitup Index: trunk/src/crosshair.c =================================================================== --- trunk/src/crosshair.c (revision 7509) +++ trunk/src/crosshair.c (revision 7510) @@ -1244,6 +1244,9 @@ } + pcb_event(PCB_EVENT_RUBBER_FIT_CROSSHAIR, "pppp", &pcb_crosshair, &pcb_marked, + &nearest_grid_x, &nearest_grid_y); + snap_data.crosshair = &pcb_crosshair; snap_data.nearest_sq_dist = crosshair_sq_dist(&pcb_crosshair, nearest_grid_x, nearest_grid_y); snap_data.nearest_is_grid = pcb_true; Index: trunk/src/event.h =================================================================== --- trunk/src/event.h (revision 7509) +++ trunk/src/event.h (revision 7510) @@ -50,6 +50,7 @@ PCB_EVENT_RUBBER_RENAME, /* rubber band: element pin/pad got renamed */ PCB_EVENT_RUBBER_LOOKUP_LINES, /* rubber band: attach rubber banded line objects to crosshair */ PCB_EVENT_RUBBER_LOOKUP_RATS, /* rubber band: attach rubber banded rat lines objects to crosshair */ + PCB_EVENT_RUBBER_FIT_CROSSHAIR, /* rubber band: fit crosshair and modify lines to keep orientation */ PCB_EVENT_GUI_SYNC, /* sync GUI state (e.g. after a menu clicked) */ Index: trunk/src_plugins/rubberband_orig/Plug.tmpasm =================================================================== --- trunk/src_plugins/rubberband_orig/Plug.tmpasm (revision 7509) +++ trunk/src_plugins/rubberband_orig/Plug.tmpasm (revision 7510) @@ -1,5 +1,8 @@ put /local/pcb/mod {rubberband_orig} -put /local/pcb/mod/OBJS [@ $(PLUGDIR)/rubberband_orig/rubberband.o @] +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/rubberband_orig/rubberband.o + $(PLUGDIR)/rubberband_orig/fgeometry.o +@] switch /local/pcb/rubberband_orig/controls case {buildin} include /local/pcb/tmpasm/buildin; end; Index: trunk/src_plugins/rubberband_orig/fgeometry.c =================================================================== --- trunk/src_plugins/rubberband_orig/fgeometry.c (nonexistent) +++ trunk/src_plugins/rubberband_orig/fgeometry.c (revision 7510) @@ -0,0 +1,130 @@ + +#include "fgeometry.h" +#include +#include + +#define MIN_COMPONENT 0.000001 + +int fvector_is_null (fvector v) +{ + return fabs(v.x) < MIN_COMPONENT && fabs(v.y) < MIN_COMPONENT; +} + +double fvector_dot (fvector v1, fvector v2) +{ + return v1.x * v2.x + v1.y * v2.y; +} + + +void fvector_normalize (fvector *v) +{ + double module = sqrt(v->x * v->x + v->y * v->y); + + v->x /= module; + v->y /= module; +} + +int fline_is_valid(fline l) +{ + return !fvector_is_null(l.direction); +} + +fline fline_create(pcb_any_line_t *line) +{ + fline ret; + + ret.point.x = line->Point1.X; + ret.point.y = line->Point1.Y; + ret.direction.x = line->Point2.X - line->Point1.X; + ret.direction.y = line->Point2.Y - line->Point1.Y; + + if (!fvector_is_null (ret.direction)) + fvector_normalize( &ret.direction ); + + return ret; +} + + +fline fline_create_from_points(struct pcb_point_s *base_point, struct pcb_point_s *other_point) +{ + fline ret; + + ret.point.x = base_point->X; + ret.point.y = base_point->Y; + ret.direction.x = other_point->X - base_point->X; + ret.direction.y = other_point->Y - base_point->Y; + + if (!fvector_is_null (ret.direction)) + fvector_normalize( &ret.direction ); + + return ret; +} + + +fvector fline_intersection(fline l1, fline l2) +{ + fvector ret; + ret.x = 0; + ret.y = 0; + + double lines_dot = fvector_dot (l1.direction, l2.direction); + if (fabs(lines_dot) > 0.990 ) + { + /* Consider them parallel. Return null point (vector) */ + return ret; + } + + /* + * *** From polygon1.c *** + * We have the lines: + * l1: p1 + s*d1 + * l2: p2 + t*d2 + * And we want to know the intersection point. + * Calculate t: + * p1 + s*d1 = p2 + t*d2 + * which is similar to the two equations: + * p1x + s * d1x = p2x + t * d2x + * p1y + s * d1y = p2y + t * d2y + * Multiplying these by d1y resp. d1x gives: + * d1y * p1x + s * d1x * d1y = d1y * p2x + t * d1y * d2x + * d1x * p1y + s * d1x * d1y = d1x * p2y + t * d1x * d2y + * Subtracting these gives: + * d1y * p1x - d1x * p1y = d1y * p2x - d1x * p2y + t * ( d1y * d2x - d1x * d2y ) + * So t can be isolated: + * t = (d1y * ( p1x - p2x ) + d1x * ( - p1y + p2y )) / ( d1y * d2x - d1x * d2y ) + * and s can be found similarly + * s = (d2y * ( p2x - p1x ) + d2x * ( p1y - p2y )) / ( d2y * d1x - d2x * d1y) + */ + + double t,s; + double p1x, p1y, d1x, d1y; + double p2x, p2y, d2x, d2y; + + p1x = l1.point.x; + p1y = l1.point.y; + d1x = l1.direction.x; + d1y = l1.direction.y; + + p2x = l2.point.x; + p2y = l2.point.y; + d2x = l2.direction.x; + d2y = l2.direction.y; + + t = (d1y * ( p1x - p2x ) + d1x * ( - p1y + p2y )) / ( d1y * d2x - d1x * d2y ); + s = (d2y * ( p2x - p1x ) + d2x * ( p1y - p2y )) / ( d2y * d1x - d2x * d1y ); + + /*printf("Intersection t=%f, s=%f\n", t, s); */ + +/* ret.x = p1x + s * d1x; + ret.y = p1y + s * d1y;*/ + + ret.x = p2x + t * d2x; + ret.y = p2y + t * d2y; + + + /*printf("Intersection x=%f, y=%f\n", ret.x, ret.y);*/ + + return ret; +} + + Index: trunk/src_plugins/rubberband_orig/fgeometry.h =================================================================== --- trunk/src_plugins/rubberband_orig/fgeometry.h (nonexistent) +++ trunk/src_plugins/rubberband_orig/fgeometry.h (revision 7510) @@ -0,0 +1,41 @@ + +#ifndef PCB_FGEOMETRY_H +#define PCB_FGEOMETRY_H + +#include "obj_common.h" + +typedef struct +{ + double x; + double y; +} fvector; + + +/* flines should be created through fline_create* functions. + * Alternatively, they can be created manually as long as + * direction is normalized + */ +typedef struct +{ + fvector point; + fvector direction; +} fline; + +int fvector_is_null(fvector v); + + +/* Any vector given to the following functions has to be non-null */ +double fvector_dot (fvector v1, fvector v2); +void fvector_normalize (fvector *v); + + +fline fline_create(pcb_any_line_t *line); +fline fline_create_from_points(struct pcb_point_s *base_point, struct pcb_point_s *other_point); + +int fline_is_valid(fline l); + +/* l1.direction and l2.direction are expected to be normalized */ +fvector fline_intersection(fline l1, fline l2); + +#endif + Index: trunk/src_plugins/rubberband_orig/rubberband.c =================================================================== --- trunk/src_plugins/rubberband_orig/rubberband.c (revision 7509) +++ trunk/src_plugins/rubberband_orig/rubberband.c (revision 7510) @@ -42,6 +42,7 @@ #include "operation.h" #include "rotate.h" #include "draw.h" +#include "crosshair.h" #include "obj_rat_draw.h" #include "obj_line_op.h" #include "obj_line_draw.h" @@ -48,6 +49,7 @@ #include "plugins.h" #include "conf_core.h" #include "layer_grp.h" +#include "fgeometry.h" #include "polygon.h" @@ -55,6 +57,9 @@ pcb_layer_t *Layer; /* layer that holds the line */ pcb_line_t *Line; /* the line itself */ pcb_point_t *MovedPoint; /* and finally the point */ + pcb_coord_t DX; + pcb_coord_t DY; + int delta_is_valid; } pcb_rubberband_t; typedef struct { @@ -674,6 +679,9 @@ ptr->Layer = Layer; ptr->Line = Line; ptr->MovedPoint = MovedPoint; + ptr->DX = -1; + ptr->DY = -1; + ptr->delta_is_valid = 0; return (ptr); } @@ -739,9 +747,9 @@ rubber_ctx_t *rbnd = user_data; pcb_rubberband_t *ptr; pcb_cardinal_t i; - pcb_coord_t dx = argv[1].d.c, dy = argv[2].d.c; + pcb_coord_t group_dx = argv[1].d.c, group_dy = argv[2].d.c; + pcb_coord_t dx = group_dx, dy = group_dy; - /* draw the attached rubberband lines too */ i = rbnd->RubberbandN; ptr = rbnd->Rubberband; @@ -754,12 +762,22 @@ pcb_coord_t x1=0,y1=0,x2=0,y2=0; if (PCB_FLAG_TEST(PCB_FLAG_RUBBEREND, ptr->Line)) { - /* 'point1' is always the fix-point */ + if (ptr->delta_is_valid) { + dx = ptr->DX; + dy = ptr->DY; + } + else { + dx = group_dx; + dy = group_dy; + } + /* 'point1' is always the fix-point */ if (ptr->MovedPoint == &ptr->Line->Point1) { x1 = ptr->Line->Point2.X; y1 = ptr->Line->Point2.Y; + pcb_coord_t a = 0; /*-25945061;*/ +/* printf ("%d\n", dy);*/ x2 = ptr->Line->Point1.X + dx; - y2 = ptr->Line->Point1.Y + dy; + y2 = ptr->Line->Point1.Y + dy + a; } else { x1 = ptr->Line->Point1.X; @@ -768,23 +786,22 @@ y2 = ptr->Line->Point2.Y + dy; } } - else if (ptr->MovedPoint == &ptr->Line->Point1) { - x1 = ptr->Line->Point1.X + dx; - y1 = ptr->Line->Point1.Y + dy; - x2 = ptr->Line->Point2.X + dx; - y2 = ptr->Line->Point2.Y + dy; + else if (ptr->MovedPoint == &ptr->Line->Point1) { + x1 = ptr->Line->Point1.X + group_dx; + y1 = ptr->Line->Point1.Y + group_dy; + x2 = ptr->Line->Point2.X + group_dx; + y2 = ptr->Line->Point2.Y + group_dy; } if ((x1 != x2) || (y1 != y2)) { XORDrawAttachedLine(x1,y1,x2,y2, ptr->Line->Thickness); - /* Draw the DRC outline if it is enabled */ if (conf_core.editor.show_drc) { pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); - XORDrawAttachedLine(x1,y1,x2,y2,ptr->Line->Thickness + 2 * (PCB->Bloat + 1) ); - pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + XORDrawAttachedLine(x1,y1,x2,y2,ptr->Line->Thickness + 2 * (PCB->Bloat + 1) ); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); } - } + } } ptr++; @@ -876,7 +893,104 @@ pcb_rubber_band_lookup_rat_lines(rbnd, type, ptr1, ptr2, ptr3); } +static void rbe_fit_crosshair(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + int i; + rubber_ctx_t *rbnd = user_data; + pcb_crosshair_t *pcb_crosshair = argv[1].d.p; + pcb_mark_t *pcb_marked = argv[2].d.p; + pcb_coord_t *x = argv[3].d.p; /* Return argument */ + pcb_coord_t *y = argv[4].d.p; /* Return argument */ + for (i=0; iRubberbandN; i++) { + rbnd->Rubberband[i].delta_is_valid = 0; + } + + /* Move keeping rubberband lines direction */ + if ((pcb_crosshair->AttachedObject.Type == PCB_TYPE_LINE) && (rbnd->RubberbandN == 2)) + { + pcb_line_t *line = (pcb_line_t*) pcb_crosshair->AttachedObject.Ptr2; + pcb_line_t *rub1 = rbnd->Rubberband[0].Line; + pcb_line_t *rub2 = rbnd->Rubberband[1].Line; + + /* Create float point-vector representations of the lines */ + fline fmain, frub1, frub2; + fmain = fline_create_from_points (&line->Point1, &line->Point2); + if (rbnd->Rubberband[0].MovedPoint == &rub1->Point1) + frub1 = fline_create_from_points (&rub1->Point1, &rub1->Point2); + else + frub1 = fline_create_from_points (&rub1->Point2, &rub1->Point1); + + if (rbnd->Rubberband[1].MovedPoint == &rub2->Point1) + frub2 = fline_create_from_points (&rub2->Point1, &rub2->Point2); + else + frub2 = fline_create_from_points (&rub2->Point2, &rub2->Point1); + + /* If they are valid (non-null directions) we carry on */ + if (fline_is_valid(fmain) && fline_is_valid(frub1) && fline_is_valid(frub2)) { + fvector fmove; + + fvector fintersection = fline_intersection(frub1, frub2); + + if (!fvector_is_null(fintersection)) { + /* Movement direction defined as from mid line to intersection point */ + fvector fmid; + fmid.x = ((double)line->Point2.X + line->Point1.X) / 2.0; + fmid.y = ((double)line->Point2.Y + line->Point1.Y) / 2.0; + fmove.x = fintersection.x - fmid.x; + fmove.y = fintersection.y - fmid.y; + } + else { + /* No intersection. Rubberband lines are parallel */ + fmove.x = frub1.direction.x; + fmove.y = frub1.direction.y; + } + + if (!fvector_is_null(fmove)) { + fvector_normalize(&fmove); + + /* Cursor delta vector */ + fvector fcursor_delta; + fcursor_delta.x = pcb_crosshair->X - pcb_marked->X; + fcursor_delta.y = pcb_crosshair->Y - pcb_marked->Y; + + /* Cursor delta projection on movement direction */ + double amount_moved = fvector_dot(fmove, fcursor_delta); + + /* Scale fmove by calculated amount */ + fvector fmove_total; + fmove_total.x = fmove.x * amount_moved; + fmove_total.y = fmove.y * amount_moved; + + /* Update values for nearest_grid and Rubberband lines */ + *x = pcb_marked->X + fmove_total.x; + *y = pcb_marked->Y + fmove_total.y; + + /* Move rubberband: fmove_totalˇnormal = fmove_rubberbandˇnormal + * where normal is the moving line normal + */ + fvector fnormal; + fnormal.x = fmain.direction.y; + fnormal.y = -fmain.direction.x; + if (fvector_dot(fnormal, fmove) < 0) { + fnormal.x = -fnormal.x; + fnormal.y = -fnormal.y; + } + double rub1_move = amount_moved * fvector_dot(fmove, fnormal) / fvector_dot(frub1.direction, fnormal); + rbnd->Rubberband[0].DX = rub1_move*frub1.direction.x; + rbnd->Rubberband[0].DY = rub1_move*frub1.direction.y; + rbnd->Rubberband[0].delta_is_valid = 1; + + double rub2_move = amount_moved * fvector_dot(fmove, fnormal) / fvector_dot(frub2.direction, fnormal); + rbnd->Rubberband[1].DX = rub2_move*frub2.direction.x; + rbnd->Rubberband[1].DY = rub2_move*frub2.direction.y; + rbnd->Rubberband[1].delta_is_valid = 1; + } + } + } +} + + static const char *rubber_cookie = "old rubberband"; void rb_uninit(void) @@ -895,6 +1009,7 @@ pcb_event_bind(PCB_EVENT_RUBBER_RENAME, rbe_rename, ctx, rubber_cookie); pcb_event_bind(PCB_EVENT_RUBBER_LOOKUP_LINES, rbe_lookup_lines, ctx, rubber_cookie); pcb_event_bind(PCB_EVENT_RUBBER_LOOKUP_RATS, rbe_lookup_rats, ctx, rubber_cookie); + pcb_event_bind(PCB_EVENT_RUBBER_FIT_CROSSHAIR, rbe_fit_crosshair, ctx, rubber_cookie); return rb_uninit; }