From d5d090afc0219781a1b7a29dcd08e2901d251008 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sat, 21 Oct 2023 23:48:56 +0200 Subject: [PATCH] better line-rectangle touch check for backward rectangle selection (intersection select) --- src/clip.c | 34 ++++++++++++++++++++++++++++++++++ src/scheduler.c | 8 ++++++++ src/select.c | 16 ++++++++++++---- src/xschem.h | 4 ++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/clip.c b/src/clip.c index 76b41ff7..f0fa3d82 100644 --- a/src/clip.c +++ b/src/clip.c @@ -38,6 +38,8 @@ static int outcode(double x,double y, double sx1, double sy1, double sx2, double return code; } + +/* clip a line (in screen coordinates) with screen boundaries */ int clip( double *xa,double *ya,double *xb,double *yb) { int outa, outb,outpoint; @@ -74,6 +76,38 @@ int clip( double *xa,double *ya,double *xb,double *yb) } } +/* clip a line (xa,ya,xb,yb) with rectangle (sx1,sy1,sx2,sy2) */ +int lineclip(double *xa,double *ya,double *xb,double *yb, + double sx1,double sy1,double sx2,double sy2) +{ + int outa, outb,outpoint; + double x,y; + outa=outcode(*xa, *ya, sx1, sy1, sx2, sy2); + outb=outcode(*xb, *yb, sx1, sy1, sx2, sy2); + while(1) + { + if(!(outa | outb)) return 1; /* line is all inside! */ + else if(outa & outb) return 0; /* line is all outside! */ + else + { + outpoint=outa? outa:outb; + if(UP & outpoint) + {x= *xa + (*xb-*xa) * (sy2 - *ya) / (*yb - *ya); y = sy2;} + else if(DOWN & outpoint) + {x= *xa + (*xb-*xa) * (sy1 - *ya) / (*yb - *ya); y = sy1;} + else if(RIGHT & outpoint) + {y= *ya + (*yb-*ya) * (sx2 - *xa) / (*xb - *xa); x = sx2;} + /* else if(LEFT & outpoint) */ + else + {y= *ya + (*yb-*ya) * (sx1 - *xa) / (*xb - *xa); x = sx1;} + if(outpoint == outa) + {*xa=x; *ya=y; outa=outcode(*xa, *ya, sx1, sy1, sx2, sy2);} + else + {*xb=x; *yb=y; outb=outcode(*xb, *yb, sx1, sy1, sx2, sy2);} + } + } +} + void clip_xy_to_short(double x, double y, short *sx, short *sy) { double ax, ay; diff --git a/src/scheduler.c b/src/scheduler.c index 28224179..e38a5e24 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -4564,6 +4564,14 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg Tcl_ResetResult(interp); } + /* test + * Testmode ... */ + else if(!strcmp(argv[1], "test") ) + { + if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} + Tcl_ResetResult(interp); + } + /* text x y rot flip text props size draw * Create a text object * x, y, rot, flip specify the position and orientation diff --git a/src/select.c b/src/select.c index e00f72b7..41f49e97 100644 --- a/src/select.c +++ b/src/select.c @@ -1531,8 +1531,12 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un for(i=0;iwires; ++i) { - if(POINTINSIDE(xctx->wire[i].x1,xctx->wire[i].y1, x1,y1,x2,y2) || - POINTINSIDE(xctx->wire[i].x2,xctx->wire[i].y2, x1,y1,x2,y2)) { + double lx1, ly1, lx2, ly2; + lx1 = xctx->wire[i].x1; + ly1 = xctx->wire[i].y1; + lx2 = xctx->wire[i].x2; + ly2 = xctx->wire[i].y2; + if(lineclip(&lx1, &ly1, &lx2, &ly2, x1,y1,x2,y2)) { xctx->ui_state |= SELECTION; /* set xctx->ui_state to SELECTION also if unselecting by area ???? */ sel ? select_wire(i,SELECTED, 1): select_wire(i,0, 1); } @@ -1598,8 +1602,12 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un } for(i=0;ilines[c]; ++i) { - if(POINTINSIDE(xctx->line[c][i].x1, xctx->line[c][i].y1, x1,y1,x2,y2) || - POINTINSIDE(xctx->line[c][i].x2, xctx->line[c][i].y2, x1,y1,x2,y2)) { + double lx1, ly1, lx2, ly2; + lx1 = xctx->line[c][i].x1; + ly1 = xctx->line[c][i].y1; + lx2 = xctx->line[c][i].x2; + ly2 = xctx->line[c][i].y2; + if(lineclip(&lx1, &ly1, &lx2, &ly2, x1,y1,x2,y2)) { xctx->ui_state |= SELECTION; sel? select_line(c,i,SELECTED,1): select_line(c,i,0,1); } diff --git a/src/xschem.h b/src/xschem.h index 425a95cd..9b9fe849 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1352,7 +1352,11 @@ extern void MyXCopyAreaDouble(Display* display, Drawable src, Drawable dest, GC double sx1, double sy1, double sx2, double sy2, double dx1, double dy1, double lw); extern void draw(void); extern void clip_xy_to_short(double x, double y, short *sx, short *sy); +/* clip a line (in screen coordinates) with screen boundaries */ extern int clip( double*,double*,double*,double*); +/* clip a line (xa,ya,xb,yb) with rectangle (sx1,sy1,sx2,sy2) */ +extern int lineclip(double *xa,double *ya,double *xb,double *yb, + double sx1,double sy1,double sx2,double sy2); extern int textclip(int x1,int y1,int x2,int y2, double xa,double ya,double xb,double yb); extern double dist_from_rect(double mx,