From 49c2cb985cc7148f956cd38860bf0dc6082bb551 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 28 Sep 2021 15:55:28 +0200 Subject: [PATCH] :bug: Fix problems with imported svgs --- common/src/app/common/path/bool.cljc | 65 ++++++++++++++--------- common/src/app/common/path/subpaths.cljc | 24 +++++++++ frontend/src/app/main/ui/shapes/bool.cljs | 9 ++-- 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/common/src/app/common/path/bool.cljc b/common/src/app/common/path/bool.cljc index 37aef3402..649e17282 100644 --- a/common/src/app/common/path/bool.cljc +++ b/common/src/app/common/path/bool.cljc @@ -13,23 +13,6 @@ [app.common.path.commands :as upc] [app.common.path.subpaths :as ups])) -(defn- reverse-command - "Reverses a single command" - [command] - - (let [{old-x :x old-y :y} (:params command) - {:keys [x y]} (:prev command) - {:keys [c1x c1y c2x c2y]} (:params command)] - - (-> command - (assoc :prev (gpt/point old-x old-y)) - (update :params assoc :x x :y y) - - (cond-> (= :curve-to (:command command)) - (update :params assoc - :c1x c2x :c1y c2y - :c2x c1x :c2y c1y))))) - (defn add-previous ([content] (add-previous content nil)) @@ -43,6 +26,37 @@ (some? prev) (assoc :prev (gsp/command->point prev)))))))) +(defn close-paths + "Removes the :close-path commands and replace them for line-to so we can calculate + the intersections" + [content] + + (loop [head (first content) + content (rest content) + result [] + last-move nil] + + (if (nil? head) + result + (let [head-p (gsp/command->point head) + head (cond + (and (= :close-path (:command head)) + (< (gpt/distance head-p last-move) 0.01)) + nil + + (= :close-path (:command head)) + (upc/make-line-to last-move) + + :else + head)] + + (recur (first content) + (rest content) + (cond-> result (some? head) (conj head)) + (if (= :move-to (:command head)) + head-p + last-move)))))) + (defn- split-command [cmd values] (case (:command cmd) @@ -192,8 +206,6 @@ ;; Reverse second content so we can have holes inside other shapes (->> content-b-split - (reverse) - (mapv reverse-command) (filter #(and (contains-segment? % content-a) (not (overlap-segment? % content-a-split))))))) @@ -207,10 +219,8 @@ (defn create-exclusion [content-a content-b] - ;; Pick all segments but reverse content-b (so it makes an exclusion) - (let [content-b' (->> (reverse content-b) - (mapv reverse-command))] - (d/concat [] content-a content-b'))) + ;; Pick all segments + (d/concat [] content-a content-b)) (defn fix-move-to @@ -237,8 +247,13 @@ (defn content-bool-pair [bool-type content-a content-b] - (let [content-a (add-previous content-a) - content-b (add-previous content-b) + (let [content-a (-> content-a (close-paths) (add-previous)) + + content-b (-> content-b + (close-paths) + (cond-> (ups/clockwise? content-b) + (ups/reverse-content)) + (add-previous)) ;; Split content in new segments in the intersection with the other path [content-a-split content-b-split] (content-intersect-split content-a content-b) diff --git a/common/src/app/common/path/subpaths.cljc b/common/src/app/common/path/subpaths.cljc index 3c4d90c68..ca92a6c30 100644 --- a/common/src/app/common/path/subpaths.cljc +++ b/common/src/app/common/path/subpaths.cljc @@ -158,3 +158,27 @@ (reverse) (mapcat :data) (into []))) + +;; https://mathworld.wolfram.com/PolygonArea.html +(defn clockwise? + "Check whether the first subpath is clockwise or counter-clock wise" + [content] + (let [subpath (->> content get-subpaths first :data)] + (loop [current (first subpath) + subpath (rest subpath) + first-point nil + signed-area 0] + + (if (nil? current) + (> signed-area 0) + + (let [{x1 :x y1 :y :as p} (upc/command->point current) + last? (nil? (first subpath)) + first-point (if (nil? first-point) p first-point) + {x2 :x y2 :y} (if last? first-point (upc/command->point (first subpath))) + signed-area (+ signed-area (- (* x1 y2) (* x2 y1)))] + + (recur (first subpath) + (rest subpath) + first-point + signed-area)))))) diff --git a/frontend/src/app/main/ui/shapes/bool.cljs b/frontend/src/app/main/ui/shapes/bool.cljs index faa3b3f99..fd9b58f94 100644 --- a/frontend/src/app/main/ui/shapes/bool.cljs +++ b/frontend/src/app/main/ui/shapes/bool.cljs @@ -35,8 +35,9 @@ (map #(get childs %)) (filter #(not (:hidden %))) (map #(stp/convert-to-path % childs)) - (mapv :content) - (mapv pb/add-previous))] + (map :content) + (map pb/close-paths) + (map pb/add-previous))] (pb/content-intersect-split content-a content-b))))] [:g.debug-bool [:g.shape-a @@ -49,7 +50,7 @@ (dissoc :fill-color :fill-opacity) (assoc :content content-b)) :frame frame}] - (for [{:keys [x y]} (gsp/content->points content-b)] + (for [{:keys [x y]} (gsp/content->points (pb/close-paths content-b))] [:circle {:cx x :cy y :r 2.5 @@ -65,7 +66,7 @@ (dissoc :fill-color :fill-opacity) (assoc :content content-a)) :frame frame}] - (for [{:keys [x y]} (gsp/content->points content-a)] + (for [{:keys [x y]} (gsp/content->points (pb/close-paths content-a))] [:circle {:cx x :cy y :r 1.25