From bc3640893c2d64cf76c1344961352505ae171079 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 7 Apr 2021 13:21:05 +0200 Subject: [PATCH] :sparkles: Remove nodes --- .../app/main/data/workspace/path/tools.cljs | 9 +-- frontend/src/app/util/geom/path.cljs | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/data/workspace/path/tools.cljs b/frontend/src/app/main/data/workspace/path/tools.cljs index ad2764dda..8fc961b7a 100644 --- a/frontend/src/app/main/data/workspace/path/tools.cljs +++ b/frontend/src/app/main/data/workspace/path/tools.cljs @@ -63,14 +63,7 @@ shape (get-in state (st/get-path state)) selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) content (:content shape) - - - - - - new-content (->> content - (filterv #(not (contains? selected-points (ugp/command->point %))))) - + new-content (ugp/remove-nodes content selected-points) [rch uch] (changes/generate-path-changes page-id shape (:content shape) new-content)] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index 7ae7bbce5..aa825e1a4 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -676,7 +676,9 @@ segments))))) -(defn split-segments [content points value] +(defn split-segments + "Given a content creates splits commands between points with new segments" + [content points value] (let [split-command (fn [[start end cmd]] (case (:command cmd) @@ -697,3 +699,74 @@ [command]))] (into [] (mapcat process-segments) content))) + +(defn remove-nodes + "Removes from content the points given. Will try to reconstruct the paths + to keep everything consistent" + [content points] + + (let [content (d/with-prev content)] + + (loop [result [] + last-handler nil + [cur-cmd prev-cmd] (first content) + content (rest content)] + + (if (nil? cur-cmd) + ;; The result with be an array of arrays were every entry is a subpath + (->> result + ;; remove empty and only 1 node subpaths + (filter #(> (count %) 1)) + ;; flatten array-of-arrays plain array + (flatten) + (into [])) + + (let [move? (= :move-to (:command cur-cmd)) + curve? (= :curve-to (:command cur-cmd)) + + ;; When the old command was a move we start a subpath + result (if move? (conj result []) result) + + subpath (peek result) + + point (command->point cur-cmd) + + old-prev-point (command->point prev-cmd) + new-prev-point (command->point (peek subpath)) + + remove? (contains? points point) + + + ;; We store the first handler for the first curve to be removed to + ;; use it for the first handler of the regenerated path + cur-handler (cond + (and (not last-handler) remove? curve?) + (select-keys (:params cur-cmd) [:c1x :c1y]) + + (not remove?) + nil + + :else + last-handler) + + cur-cmd (cond-> cur-cmd + ;; If we're starting a subpath and it's not a move make it a move + (and (not move?) (empty? subpath)) + (assoc :command :move-to + :params (select-keys (:params cur-cmd) [:x :y])) + + ;; If have a curve the first handler will be relative to the previous + ;; point. We change the handler to the new previous point + (and curve? (not (empty? subpath)) (not= old-prev-point new-prev-point)) + (update :params merge last-handler)) + + head-idx (dec (count result)) + + result (cond-> result + (not remove?) + (update head-idx conj cur-cmd))] + (recur result + cur-handler + (first content) + (rest content))))))) +