From 64accaa84262c5b017a36e288377ba644b739240 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 25 Aug 2023 10:21:48 +0200 Subject: [PATCH] :zap: Simplify has-point? impl for non-path shapes --- .../src/app/common/geom/shapes/intersect.cljc | 32 ++++++++++++++++--- .../test/common_tests/geom_shapes_test.cljc | 12 +++++++ .../app/main/data/workspace/selection.cljs | 3 +- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/common/src/app/common/geom/shapes/intersect.cljc b/common/src/app/common/geom/shapes/intersect.cljc index 665ac1e594..e2810e61e7 100644 --- a/common/src/app/common/geom/shapes/intersect.cljc +++ b/common/src/app/common/geom/shapes/intersect.cljc @@ -7,13 +7,15 @@ (ns app.common.geom.shapes.intersect (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.path :as gpp] [app.common.geom.shapes.text :as gte] - [app.common.math :as mth])) + [app.common.math :as mth] + [app.common.pages.helpers :as cph])) (defn orientation "Given three ordered points gives the orientation @@ -335,13 +337,33 @@ (let [lines (grc/rect->lines rect)] (is-point-inside-evenodd? point lines))) -(defn has-point? - "Check if the shape contains a point" +(defn slow-has-point? [shape point] - (let [lines (points->lines (:points shape))] - ;; TODO: Will only work for simple shapes + (let [lines (points->lines (dm/get-prop shape :points))] (is-point-inside-evenodd? point lines))) +(defn fast-has-point? + [shape point] + (let [x1 (dm/get-prop shape :x) + y1 (dm/get-prop shape :x) + x2 (+ x1 (dm/get-prop shape :width)) + y2 (+ y1 (dm/get-prop shape :height)) + px (dm/get-prop point :x) + py (dm/get-prop point :y)] + + (and (>= px x1) + (<= px x2) + (>= py y1) + (<= py y2)))) + +(defn has-point? + [shape point] + (if (or ^boolean (cph/path-shape? shape) + ^boolean (cph/bool-shape? shape) + ^boolean (cph/circle-shape? shape)) + (slow-has-point? shape point) + (fast-has-point? shape point))) + (defn rect-contains-shape? [rect shape] (->> shape diff --git a/common/test/common_tests/geom_shapes_test.cljc b/common/test/common_tests/geom_shapes_test.cljc index ce8d63060a..4e4ea3829a 100644 --- a/common/test/common_tests/geom_shapes_test.cljc +++ b/common/test/common_tests/geom_shapes_test.cljc @@ -10,6 +10,7 @@ [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.intersect :as gsin] [app.common.geom.shapes.transforms :as gsht] [app.common.math :as mth :refer [close?]] [app.common.types.modifiers :as ctm] @@ -224,3 +225,14 @@ (grc/rect->points) (gsh/transform-points (gmt/rotate-matrix 45))) (gmt/matrix (* (mth/cos g45) 2) (* (mth/sin g45) 2) (* (- (mth/sin g45)) 4) (* (mth/cos g45) 4) 0 0)))) + + +(t/deftest shape-has-point-pred + (let [{:keys [points] :as shape} (create-test-shape :rect {}) + point1 (first points) + point2 (update point1 :x - 100)] + (t/is (true? (gsin/fast-has-point? shape point1))) + (t/is (true? (gsin/slow-has-point? shape point1))) + (t/is (false? (gsin/fast-has-point? shape point2))) + (t/is (false? (gsin/fast-has-point? shape point2))) + )) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 6dc81868a3..b13ed7bc87 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -318,8 +318,7 @@ ;; We need to reverse the children because if two children ;; overlap we want to select the one that's over (and it's ;; in the later vector position - selected (->> children - reverse + selected (->> (reverse children) (d/seek #(gsh/has-point? % position)))] (when selected (rx/of (select-shape (:id selected))))))))