From 5887be6eda82b2aecff4a0d0b5ce2b8b6e58f2c3 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Sun, 12 Jan 2020 20:16:48 +0100 Subject: [PATCH] select filled elements by clicking inside (#340) --- src/element/collision.ts | 55 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/element/collision.ts b/src/element/collision.ts index 58c65601..2201bbc1 100644 --- a/src/element/collision.ts +++ b/src/element/collision.ts @@ -50,10 +50,25 @@ export function hitTest( ty /= t; }); - return Math.hypot(a * tx - px, b * ty - py) < lineThreshold; + if (element.backgroundColor !== "transparent") { + return ( + a * tx - (px - lineThreshold) >= 0 && b * ty - (py - lineThreshold) >= 0 + ); + } else { + return Math.hypot(a * tx - px, b * ty - py) < lineThreshold; + } } else if (element.type === "rectangle") { const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); + if (element.backgroundColor !== "transparent") { + return ( + x > x1 - lineThreshold && + x < x2 + lineThreshold && + y > y1 - lineThreshold && + y < y2 + lineThreshold + ); + } + // (x1, y1) --A-- (x2, y1) // |D |B // (x1, y2) --C-- (x2, y2) @@ -67,7 +82,7 @@ export function hitTest( x -= element.x; y -= element.y; - const [ + let [ topX, topY, rightX, @@ -78,6 +93,42 @@ export function hitTest( leftY ] = getDiamondPoints(element); + if (element.backgroundColor !== "transparent") { + // TODO: remove this when we normalize coordinates globally + if (topY > bottomY) [bottomY, topY] = [topY, bottomY]; + if (rightX < leftX) [leftX, rightX] = [rightX, leftX]; + + topY -= lineThreshold; + bottomY += lineThreshold; + leftX -= lineThreshold; + rightX += lineThreshold; + + // all deltas should be < 0. Delta > 0 indicates it's on the outside side + // of the line. + // + // (topX, topY) + // D / \ A + // / \ + // (leftX, leftY) (rightX, rightY) + // C \ / B + // \ / + // (bottomX, bottomY) + // + // https://stackoverflow.com/a/2752753/927631 + return ( + // delta from line D + (leftX - topX) * (y - leftY) - (leftX - x) * (topY - leftY) <= 0 && + // delta from line A + (topX - rightX) * (y - rightY) - (x - rightX) * (topY - rightY) <= 0 && + // delta from line B + (rightX - bottomX) * (y - bottomY) - + (x - bottomX) * (rightY - bottomY) <= + 0 && + // delta from line C + (bottomX - leftX) * (y - leftY) - (x - leftX) * (bottomY - leftY) <= 0 + ); + } + return ( distanceBetweenPointAndSegment(x, y, topX, topY, rightX, rightY) < lineThreshold ||