Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Is it possible to write a LISP that allows objects from one hatch to be made islands for another hatch?

20 REPLIES 20
Reply
Message 1 of 21
edushka228
885 Views, 20 Replies

Is it possible to write a LISP that allows objects from one hatch to be made islands for another hatch?

The task is to create the visibility of hatches overlapping each other. For example, we have two hatches: first add the first hatch, then add the second hatch so that the objects of the first hatch become islands for the second hatch. If we add a third hatch, it will look like it is located under the two previous hatches

 

8c3Xc.png

Screenshot_1.jpg

20 REPLIES 20
Message 2 of 21
Kent1Cooper
in reply to: edushka228

Along the lines of my assumed approach at your Topic in the AutoCAD Forum [this is the better place for it], in very simplest terms, this seems to do what you want:

 

(defun C:HHB (/ hatch pieces); = Hatch with Hatch Boundaries
  (setq hatch (car (entsel "\nSelect Hatch to use as Hatch bounaries: ")))
  (command
    "_.copy" hatch "" "0,0" "@"
    "_.explode" "_last"
  )
  (setq pieces (ssget "_P"))
  (initdia)
  (command-s "_.hatch"); allow completion of command, then:
  (command "_.erase" pieces "")
)

 

It worked for me with the HEX pattern inside a Circle, putting GRAVEL in around the hexagonal islands:

Kent1Cooper_0-1712924764127.png

But bear in mind that it could be affected by the details of the pattern definition, if the pieces resulting from Exploding it don't meet precisely, which could become more of an issue if far from the origin.

 

It doesn't do various things it could, like verify that you picked a Hatch object, and if you would usually use it with only a limited choice of patterns [many don't make closed shapes and wouldn't work as boundaries], check whether it's one of those.  And the usual other stuff -- Undo begin/end wrapping, Layer control if you want, *error* handling if appropriate, command-echo suppression, etc.

Kent Cooper, AIA
Message 3 of 21
edushka228
in reply to: Kent1Cooper

Why doesn't it work with custom hatches?

Message 4 of 21
edushka228
in reply to: Kent1Cooper

If you manually apply the explode method to custom hatches, everything works. Is there any way to improve the code?

Message 5 of 21
Kent1Cooper
in reply to: edushka228


@edushka228 wrote:

Why doesn't it work with custom hatches?


Not enough information.

 

Do you mean a custom Hatch as the islands part, or as the filling-around-them part?  If the islands, I suspect the pattern definition is not precise enough for the islands produced to be closed shapes, but there are little gaps at corners, etc.  If that's the case, you may be able to help the situation by ensuring the Hatch origin is within or very close to it, because any "drift" of line positions, from imprecision in the definition, increases with distance from the origin.

 

And what do you mean by "doesn't ... work"?  Your infill bleeds inside the islands?  [See my suspicion above.]  It doesn't get rid of the pieces from the Exploded pattern?  Something else?

Kent Cooper, AIA
Message 6 of 21
Kent1Cooper
in reply to: edushka228


@edushka228 wrote:

If you manually apply the explode method to custom hatches, everything works. Is there any way to improve the code?


Since it doesn't suppress command-echoing, check the command-line history after you use it unsuccessfully, where you may find some indication of what's going wrong.

 

EDIT:  I've now tried it on several other patterns for the islands part, both some that come with AutoCAD and some custom ones, and it has worked as expected.  [Acad2020 here -- I can try it on 2024 elsewhere, later.]

Kent Cooper, AIA
Message 7 of 21
marko_ribar
in reply to: edushka228

This is the version that worked for me...

I used BricsCAD V23

 

(defun C:HHB ( / hatch el ex s ); = Hatch with Hatch Boundaries
  (setq hatch (car (entsel "\nSelect Hatch to use as Hatch bounaries: ")))
  (command "_.copy" hatch "" "0,0" "@")
  (setq el (entlast) s (ssadd))  
  (command "_.explode" "_l")
  (command "_.pedit" "_m" "_p" "" "_j")
  (while (< 0 (getvar (quote cmdactive)))
    (command "")
  )
  (while (setq el (entnext el))
    (if
      (and
        (= (cdr (assoc 0 (setq ex (entget el)))) "LWPOLYLINE")
        (= 1 (logand 1 (cdr (assoc 70 ex))))
      )
      (ssadd el s)
    )
  )
  (foreach pl (vl-remove-if (quote listp) (mapcar (function cadr) (ssnamex s)))
    (command "_.wipeout" "_p" pl "_y")
  )
  (princ)
)

Or this - the same, but without sel.set... Instead - used list of lwpolylines...

 

(defun C:HHB ( / hatch el ex ellst ); = Hatch with Hatch Boundaries
  (setq hatch (car (entsel "\nSelect Hatch to use as Hatch bounaries: ")))
  (command "_.copy" hatch "" "0,0" "@")
  (setq el (entlast))  
  (command "_.explode" "_l")
  (command "_.pedit" "_m" "_p" "" "_j")
  (while (< 0 (getvar (quote cmdactive)))
    (command "")
  )
  (while (setq el (entnext el))
    (if
      (and
        (= (cdr (assoc 0 (setq ex (entget el)))) "LWPOLYLINE")
        (= 1 (logand 1 (cdr (assoc 70 ex))))
      )
      (setq ellst (cons el ellst))
    )
  )
  (foreach pl ellst
    (command "_.wipeout" "_p" pl "_y")
  )
  (princ)
)

 

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 8 of 21
marko_ribar
in reply to: marko_ribar

This worked on AutoCAD 2022...

I guess it'll (should) work and on AutoCAD 2024...

 

(defun C:HHB ( / hatch el regs ellst ); = Hatch with Hatch Boundaries
  (setq hatch (car (entsel "\nSelect Hatch to use as Hatch bounaries: ")))
  (command "_.copy" hatch "" "0,0" "@")
  (command "_.explode" "_l")
  (setq el (entlast))
  (command "_.region" (ssget "_p"))
  (while (< 0 (getvar (quote cmdactive)))
    (command "")
  )
  (while (setq el (entnext el))
    (setq regs (cons el regs))
  )
  (foreach el regs
    (command "_.explode" el)
    (while (< 0 (getvar (quote cmdactive)))
      (command "")
    )
    (command "_.pedit" "_m" (ssget "_p") "" "_j" 1e-3)
    (while (< 0 (getvar (quote cmdactive)))
      (command "")
    )
    (setq ellst (cons (entlast) ellst))
  )
  (foreach pl ellst
    (command "_.wipeout" "_p" pl "_y")
  )
  (princ)
)

 

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 9 of 21
edushka228
in reply to: Kent1Cooper

My final task is to write a script that will select all hatches in the figure and for each area painted with multiple hatches, apply the overlay script you implemented in the code above. I will define the order of overlaying later, for now it can be done randomly.

For example, we have areas with multiple hatches (picture on the left). We just run the script and we get the result as in the picture on the right

 

edushka228_0-1713030449362.png

 

Message 10 of 21
marko_ribar
in reply to: edushka228

What you expect is not doable, but you can wrap my latest code in (while) loop and pick overlayed hatches multiple times... You should get picture you described and showed...

 

(defun C:HHB ( / osm hatch el regs ellst ); = Hatch with Hatch Boundaries

  (defun *error* ( m )
    (if osm
      (setvar (quote osmode) osm)
    )
    (if m
      (prompt m)
    )
    (princ)
  )

  (setq osm (getvar (quote osmode)))
  (setvar (quote osmode) 0)
  (while (setq hatch (car (entsel "\nSelect Hatch to use as Hatch wipeouts - ENTER to FINISH...")))
    (gc)
    (repeat 2
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.copy" hatch "" "0,0" "@"))
    )
    (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.explode" "_l"))
    (setq el (entlast) regs nil)
    (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.region" (ssget "_p") ""))
    (while (setq el (entnext el))
      (setq regs (cons el regs))
    )
    (setq ellst nil)
    (foreach el regs
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.explode" el))
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.pedit" "_m" (ssget "_p") "" "_j" 1e-3 ""))
      (setq ellst (cons (entlast) ellst))
    )
    (setq el (entlast))
    (foreach pl ellst
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.wipeout" "_p" pl "_y"))
    )
    (while (setq el (entnext el))
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.draworder" el "" "_f"))
    )
  )
  (*error* nil)
)

 

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 11 of 21
edushka228
in reply to: marko_ribar

your code causes an infinite call to specify the parameters of the polyline

Message 12 of 21
Kent1Cooper
in reply to: edushka228


@edushka228 wrote:

.... I will define the order of overlaying later, for now it can be done randomly. ....


I don't think it can be done randomly.  Would it not be critical that the Hatch pattern that makes closed shapes must be done first, and only after that, the one that does not?

Kent Cooper, AIA
Message 13 of 21
edushka228
in reply to: Kent1Cooper

Let me explain the situation to you: my python code using autocad com api creates hatches in areas. As you already understood, there can be several hatches in one area, and the order in which they are drawn depends on the name of this hatch.

 

For example, we first created the HEX hatch, then STARS, then ANSI31. So, first we create HEX, then we create STARS so as to take into account the HEX elements as islands for STARS. Then we add an ANSI31 hatch to this area so that its islands are considered to be HEX and STARS elements.

 

There can be any number of hatches in one area (usually 1-5). And to be honest, I don’t yet know exactly how to build a Lisp script to achieve this goal. Either run this in parallel with adding new hatches, or run the script when all the hatches have already been created. Which option do you think is the most successful?

Message 14 of 21
marko_ribar
in reply to: edushka228


@edushka228 wrote:

your code causes an infinite call to specify the parameters of the polyline


Are you sure you know what are you talking about??? I've tested my code on both AutoCAD 2022 and BricsCAD V23 and it worked perfectly... You just have to pick correct hatch one by one... Your strategy to do it by just single call of lisp is somewhat cumbersome... It'll be much better to do it semi automatically then fully automatic... You'll never know what DWG files you'll get to work with, so order of creation of hatches IMHO doesn't have sense... Please recheck my posted last code as I've changed it just slightly to be more appllicable and with older versions of AutoCAD prior implementation of (command-s) function into AutoLISP...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 15 of 21
edushka228
in reply to: Kent1Cooper

Should I create a new post describing the entire request with all the details?

Message 16 of 21
marko_ribar
in reply to: edushka228

Here is how Kent's version works, at least I think he was thinking like this - my mod...

 

(defun C:HHB-new ( / *error* osm hpi hatch el s ); = Hatch with Hatch Boundaries

  (defun *error* ( m )
    (if osm
      (setvar (quote osmode) osm)
    )
    (if hpi
      (setvar (quote hpislanddetection) hpi)
    )
    (if m
      (prompt m)
    )
    (princ)
  )

  (setq osm (getvar (quote osmode)))
  (setvar (quote osmode) 0)
  (setq hpi (getvar (quote hpislanddetection)))
  (setvar (quote hpislanddetection) 1)
  (while (setq hatch (car (entsel "\nPick boundary hatch...ENTER to FINISH...")))
    (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.zoom" "_ob" hatch))
    (repeat 2
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.copy" hatch "" (list 0.0 0.0 0.0) "@"))
    )
    (setq el (entlast) s (ssadd))
    (command "_.explode" "_l")
    (while (< 0 (getvar (quote cmdactive)))
      (command "")
    )
    (if (not (eq el (entlast)))
      (while (setq el (entnext el))
        (if (not (= (cdr (assoc 0 (entget el))) "HATCH"))
          (ssadd el s)
        )
      )
    )
    (setq el (entlast))
    (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.pedit" "_m" s "" "_j" 1e-3 ""))
    (alert "Pick point between closed shapes of boundary hatch from HATCH dialog box - upper-right button (pick point)...")
    (initdia)
    (command "_.hatch")
    (while (< 0 (getvar (quote cmdactive)))
      (command "\\")
    )
    (setq s (ssadd))
    (if (not (eq el (entlast)))
      (while (setq el (entnext el))
        (if (= (cdr (assoc 0 (entget el))) "LWPOLYLINE")
          (ssadd el s)
        )
      )
    )
    (if (and s (= (type s) (quote pickset)) (> (sslength s) 0))
      (vl-catch-all-apply (if command-s (function command-s) (function vl-cmdf)) (list "_.erase" s ""))
    )
  )
  (*error* nil)
)

https://streamable.com/b93u0h 

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 17 of 21
Kent1Cooper
in reply to: marko_ribar

Yes, something like that, except that after the first Hatch, it should be possible to use (entlast) for the selection of the Hatch to Copy/Explode/etc., not requiring the User to pick it.  Also, a specific sequence of patterns could be built in, with their appropriate scales and rotations, if there are typical combinations.

 

But I think it would still always be necessary to ask the User to pick in the open area they want to Hatch in, at each step.  I don't see how finding the right place to pick in could be automated, i.e. how to guarantee that a calculated point is outside the closed-shape portions of all Hatches drawn so far.  [Maybe it could be done with a very specific series of patterns and careful control of the origin points and scales and rotations of each.]

 

Nor do I think it could be done by automated object selection only, at least not after the second Hatch, because I expect once you get more than one pattern of closed shapes drawn around each other, some shapes from newer ones will partially overlap or could even enclose those from earlier ones, and there will likely be ambiguities about what constitutes an "island."

 

At the least [and applicable whether by point pick or object selection], you would need to ensure the Style for islands is "Outer," not "Normal."  This is the kind of thing that could happen under "Normal" Style, if the yellow SQUARE pattern was first, the red HEX pattern second, and the green DASH pattern last:

Kent1Cooper_0-1713189993911.png

Note the bit of DASH pattern inside the yellow square in the middle, and inside the partial red hexagon at lower left, which I suspect you would not want.

 

Maybe that would never happen in the sequence(s) of patterns you would use, if they get successively smaller so that nothing newer can ever fully enclose something earlier.

Kent Cooper, AIA
Message 18 of 21
marko_ribar
in reply to: Kent1Cooper

Yes, it should be set to "Outer"... Then greens should not occupy squares and hexagons like in your picture...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 19 of 21
marko_ribar
in reply to: marko_ribar

I don't know - but I am guessing... With 2 my last codes, I think OP meight achive what's supposed to be... I've added error handler and set necessary system variables - for "Outer" - it's HPISLANDDETECTION - should be set to 1... So first step if he needs 3 hatches like in your picture - Kent's attachment is to use my HHB.lsp and create wipeouts for ex. triangles over hexagons... I've coded 2 times copy hatches so that originals stays in place... Then OP should use HHB-new.lsp - my last posted code and pick point on empty space between those 2 hatches - that's Kent's green hatch... As island detection is set to "Outer" it shoud do well, avoiding to fill inner hatchings...

But if OP has more than 3 to do, OP should apply my HHB.lsp more times and only at the end HHB-new.lsp... I've described procedure... But it's all semi automatic - so no full automatisation - that's over my head and I think that OP should agree with me, as HATCH origin point meight be 0,0 , but it could be anywhere and I think that there is no help for this kind of situations...HHB.png

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 20 of 21
edushka228
in reply to: marko_ribar

It's a shame that you can't fully automate this process. Thank you for the help you have provided. Check out my new post, there may be some information there to help us find a solution - https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-do-i-write-a-lisp-program-that-m....

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost