;; gb-split-lines-and-export.lsp (in-package :gb-custom) (use-package :oli) (defun sd-vec-equal-4-p (vec1 vec2) (sd-vec-equal-p vec1 vec2 :resolution 1e-4) ) (sd-defdialog 'gb-split-lines-and-export :dialog-title "AE: Linien aufteilen und Punkte exportieren" :toolbox-button t :variables '( (one_workplane :value-type :wp :title "Arbeitsebene" :initial-value nil :modifies nil :initial-visible nil ) ("Startbedingungen") (start_segm :title "Startsegment" :value-type :edge-2d :multiple-items nil :after-input (progn (setf one_workplane (sd-inq-parent-obj start_segm)) (setf init_pnt nil) ) ) (init_pnt :value-type :point-2d :title "Startpunkt" ) ("Ausgabe") (segm_len :value-type :positive-length :title "Segmentlänge" :initial-value 1.0 ) (with_z_coord :title "mit z-Koordinate" :toggle-type :wide-toggle :value-type :boolean :initial-value t ) (skip_short_lines :title "kurze Linien zusammenfassen" :toggle-type :wide-toggle :value-type :boolean :initial-value nil ) (OutFile :value-type :filename :title "Datei" :direction :output :if-exist :confirm-overwrite :initialdirectory (sd-get-current-working-directory) :filename-incl-path t :initialPattern "*.csv" :initial-value '("points.csv" :overwrite) ) ) :ok-action '(let (edge_struct edge_length parm_start parm_end parm_len no_of_segm s_val coords start_pnt end_pnt last_pnt next_segm continue_loop neighbors next_candidate no_of_edges no_of_points no_of_edges_on_wp exit_result pnt_list previous_coords skipped_pnt curr_distance short_pnt_list ) (sd-show-console-window) (setf no_of_edges 0) (setf no_of_edges_on_wp (length (sd-call-cmds (get_selection :NO_HIGHLIGHT :select :selected_wp one_workplane :edge_2d :all_2d) :failure nil))) (print "writing / preparing OutFile ...") (format t "~%") (with-open-file (outStream (first OutFile) :direction :output :if-exists :supersede :if-does-not-exist :create) (setf last_pnt init_pnt) (setf next_segm start_segm) (setf continue_loop t) (loop while continue_loop do (incf no_of_edges) (format t "[ ~a / ~a ]~a" no_of_edges no_of_edges_on_wp #\Return) ; create point starting at last_pnt (setf edge_struct (sd-inq-edge-geo next_segm :dest-space one_workplane)) (setf start_pnt (sd-edge-start-pnt edge_struct)) (setf end_pnt (sd-edge-end-pnt edge_struct)) (setf edge_length (sd-call-cmds (measure_dist :edge_length next_segm) :failure nil)) (if (sd-vec-equal-4-p last_pnt start_pnt) ; vorwärts (progn (setf last_pnt end_pnt) (setf parm_start (sd-edge-s-start edge_struct)) (setf parm_end (sd-edge-s-end edge_struct)) ) ; rückwärts (progn (setf last_pnt start_pnt) (setf parm_start (sd-edge-s-end edge_struct)) (setf parm_end (sd-edge-s-start edge_struct)) ) ) (setf parm_len (- parm_end parm_start)) (setf no_of_segm (ceiling (/ edge_length segm_len))) (setf parm_segm_len (/ parm_len no_of_segm)) (dotimes (i no_of_segm) (setf s_val (+ parm_start (* i parm_segm_len))) (setf coords (getf (sd-inq-edge-pnt next_segm :s s_val :coordinates t :dest-space one_workplane) :coordinates)) (push coords pnt_list) (unless skip_short_lines (gb-write-pnt-to-stream coords with_z_coord outStream) ) ) (setf neighbors (sd-call-cmds (get_selection :NO_HIGHLIGHT :focus_type *sd-edge-2d-seltype* :select :selected_wp one_workplane :edge_2d :by_vertex_2d (sd-gpnt3d-to-2d last_pnt)) :failure nil)) (if (or (> (length neighbors) 2) (= (length neighbors) 1)) ; Gabel bzw. Ende (setf next_candidate nil) (if (equal (first neighbors) next_segm) ; den haben wir gerade bearbeitet (setf next_candidate (second neighbors)) ; dann muss es der andere sein (setf next_candidate (first neighbors)) ) ) (if next_candidate (setf next_segm next_candidate) ; hier geht's weiter in der Schleife (progn ; hat nur einen Nachbarn, Ende des offenen Linienzugs erreicht ; last point handling (setf coords last_pnt) (push coords pnt_list) (unless skip_short_lines (gb-write-pnt-to-stream coords with_z_coord outStream) ) ; last point handling done (setf exit_result "Offener Linienzug") (setf continue_loop nil) (print last_pnt) ) ) (when (sd-vec-equal-p last_pnt init_pnt) ; wir sind einmal rum --> Feierabend ; last point handling, auch bei geschlossenen Liniezzug (setf coords last_pnt) (push coords pnt_list) (unless skip_short_lines (gb-write-pnt-to-stream coords with_z_coord outStream) ) ; last point handling done (setf exit_result "Geschlossener Linienzug") (setf continue_loop nil) ) ) (setf pnt_list (reverse pnt_list)) ; ggf. kurze Abstände bereinigen (setf no_of_points (length pnt_list)) (when skip_short_lines (dotimes (i no_of_points) (if (or (= i 0) (= i (- no_of_points 1))) ; erster oder letzter Punkt in Liste (progn ; erster oder letzter Punkt in Liste immer schreiben (when skipped_pnt ; vorletzter Punkt könnte ausgelassen worden sein (gb-write-pnt-to-stream skipped_pnt with_z_coord outStream) (push skipped_pnt short_pnt_list) ) (setf coords (nth i pnt_list)) (gb-write-pnt-to-stream coords with_z_coord outStream) (push coords short_pnt_list) (setf previous_coords coords) ) (progn (setf coords (nth i pnt_list)) (setf curr_distance (sd-vec-length (sd-vec-subtract coords previous_coords))) (if (> curr_distance segm_len) ; wir sind zu weit (if skipped_pnt (progn ; (gb-write-pnt-to-stream skipped_pnt with_z_coord outStream) (push skipped_pnt short_pnt_list) (setf curr_distance (sd-vec-length (sd-vec-subtract coords skipped_pnt))) (if (> curr_distance segm_len) (progn ; viel zu weit gesprungen (setf previous_coords coords) (gb-write-pnt-to-stream coords with_z_coord outStream) (push coords short_pnt_list) (setf skipped_pnt nil) ) (progn ; der vorige war gut, der jetzige nicht weit genug (setf previous_coords skipped_pnt) (setf skipped_pnt coords) ) ) ) (progn (gb-write-pnt-to-stream coords with_z_coord outStream) (push coords short_pnt_list) (setf previous_coords coords) ) ) (setf skipped_pnt coords) ; übersprungenen Punkt merken ) ) ) ) (setf pnt_list (reverse short_pnt_list)) (setf no_of_points (length pnt_list)) ) ) (sd-display-message (format nil "~a~%~a von ~a Linien bearbeitet~%~a Punkte geschrieben" exit_result no_of_edges no_of_edges_on_wp no_of_points)) (sd-hide-console-window) ) ) (defun gb-write-pnt-to-stream (coords with_z_coord outStream) (if with_z_coord (format outStream "~,6f,~,6f,~,6f~%" (gpnt3d_x coords) (gpnt3d_y coords) (gpnt3d_z coords)) (format outStream "~,6f,~,6f~%" (gpnt3d_x coords) (gpnt3d_y coords)) ) ) (sd-defdialog 'gb-create-spline-from-csv :dialog-title "Spline aus csv erstellen" :toolbox-button t :variables '( (name_spline :title "Name Drahtteil" :value-type :string :initial-value "spline" ) (InFile :value-type :filename :title "Datei" :direction :input :initialdirectory (sd-get-current-working-directory) :filename-incl-path t :initialPattern "*.csv" :initial-value '("points.csv" nil) ) ) :ok-action '(let (done line pnt_list is_closed_loop continue_loop coords remaining_points load_file load_file_dir) (with-open-file (inStream (first InFile) :direction :input) (setf done nil) (loop until done do (setf line (read-line inStream nil 'eof)) (if (eq line 'eof) (setf done t) (push (sd-read-from-string line) pnt_list) ) ) ) (setf pnt_list (reverse pnt_list)) (setf load_file_dir (format nil "~a/" (sd-convert-filename-from-platform (sd-sys-getenv "TEMP")))) ; braucht ein / am Ende (setf load_file (sd-gen-unique-filename load_file_dir :extension ".lsp")) ; unix-style (with-open-file (outStream load_file :direction :output :if-exists :supersede :if-does-not-exist :create) (if (< (length pnt_list) 900) (progn ; geht in einem Rutsch (if (sd-vec-equal-p (first pnt_list) (first (last pnt_list))) ; geschlossener Linienzug (progn (setf is_closed_loop t) (setf pnt_list (butlast pnt_list)) ) (setf is_closed_loop nil) ) (format outStream "(create_bspline :wire_part \"/~a\" ~{~a~^ ~}" name_spline pnt_list) (if is_closed_loop (format outStream " :end_condition :CLOSED)~%") (format outStream ")~%") ) ) (progn ; geht nur in 800er Paketen, zur Not auch 900 am Stück (setf continue_loop t) (setf coords nil) (loop while continue_loop do (format outStream "(create_bspline :wire_part \"/~a\"" name_spline) (when coords ; ersten Punkt = letzter Punkt vor Schleifendurchlauf zuvor (format outStream " ~a" coords) ) (setf remaining_points (length pnt_list)) (if (< remaining_points 900) (setf continue_loop nil) ; das geht auf einmal (setf remaining_points 800) ; sonst: 800er Pakete ) (dotimes (i remaining_points) (setf coords (pop pnt_list)) (format outStream " ~a" coords) ) (format outStream ")~%") ) ) ) ) (sd-call-cmds (gb-load-loadfile :loadfile load_file) :failure nil) ; WA undo buffer, geht auch schneller (delete-file load_file) ) ) (sd-defdialog 'gb-load-loadfile :variables '( (loadfile :value-type :string ) ) :ok-action '(load loadfile) )