better line-rectangle touch check for backward rectangle selection (intersection select)

This commit is contained in:
stefan schippers 2023-10-21 23:48:56 +02:00
parent 5c27e48ccf
commit d5d090afc0
4 changed files with 58 additions and 4 deletions

View File

@ -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;

View File

@ -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

View File

@ -1531,8 +1531,12 @@ void select_touch(double x1,double y1, double x2, double y2, int sel) /*added un
for(i=0;i<xctx->wires; ++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;i<xctx->lines[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);
}

View File

@ -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,