Jump to content

Select and return polylines names inside hatched areas


Recommended Posts

Posted

Hello,

 

I've been having trouble lately making an autolisp program that allows me to return the names of buildings that are included (totally or not) in a hatched area.
In my case, the colour of the hatched area is important but I'm not going to linger on the colour because if the code works for one colour there shouldn't be any problems for the others.

 

Here's the considered approach:
- select the hatches that might contain buildings
- analyse each hatch and check whether buildings are actually contained within it
- create a list of the buildings' names contained in the hatches and write the names in an Excel file

 

The hatches in question can be of any shape (rectangular, circular, etc.)

 

An example of an autocad file is attached:
- a layer "polylines" containing the polylines representing the outlines of the buildings
- a layer "numero" containing the names of the buildings (inside the outlines)
- a final layer "hatch" containing the hatches

Test AUTOCAD.dwg

 

This is the basis of my code:

 

   (setq names (ssadd))
   (setq Build (ssadd))	

  ; selecting the hatches and get their outlines
  
   (if (setq ss (ssget "x" (list '(0 . "HATCH") '(62 . 4)))) ; blue hactches
     (repeat (setq i (sslength ss))
       (setq Contours (mapcar 'cdr (vl-remove-if-not '(lambda (p) (= (car p) 10)) (entget (ssname ss (setq i (1- i)))))))
       (setq Contours (cdr Contours)) ; "Contours" = building outlines
       (setq Contours (reverse (cdr (reverse Contours))))

  ;get a selection of the polylines inside the hatches
       
       (if Contours
	 	(progn
	   		(setq ss_bat (ssget "_CP" Contours '((0 . "LWPOLYLINE") (8 . "polylignes"))))

			[...]; get the list of each building to get the names after (see lines below) -> fill "Build" 

			)
		(princ "no contours")
		)
       )
     )


; get the list of names of the buildings
  
  (repeat (setq j (sslength sel))
           (if 
               (setq sel (ssget "_CP" 
                   (mapcar 'cdr 
                       (vl-remove-if-not
                          '(lambda (p) (= (car p) 10)) 
                           (entget (ssname Build (setq j (1- j))))
                       )
                   )
		  '((0 . "TEXT,MTEXT") (8 . "numero")))
               )
	     (progn
	       (setq text (cdr (assoc 1 (entget (ssname sel 0)))))
	       (setq names (cons text names))
	       )
	     )
    )

 

I have 2 problems at the moment:
- if the hatches are in the shape of a circle, I don't have enough points when I want to retrieve the outline to accurately determine whether a building is in the hatched area or not.
- I don't know how to get a list of each individual polyline from the building selection (see the [...] inside the code above)

 

If you could give me any hints or help, I'd be very grateful.

 

Thanks

 

Posted (edited)

Yes
Getting the list of hatch points is one of the biggest difficulties in your program, especially if it is circular hatching or similar.
You cannot get a coherent perimeter from the entity list.

I tried a couple of times but had to resign myself to doing it with 'hatchedit'.

Is it possible that there is someone who can prove otherwise?

Edited by GLAVCVS
Posted

I used HatchB.lsp and yes got a pline as the defining shape, it appears to have two vertices so could check for that and make a series of points that would be the pline as facets.

 

; may be able to use (setq ent (entlast)) if a pline has been made with 2 points.
(setq ent (car (entsel "\nPick hatch boundary ")))
(setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent))))
(setq mp (mapcar '* (mapcar '+ (car co-ord) (cadr co-ord)) '(0.5 0.5)))
(setq rad (distance mp (car co-ord)))
(setq inc (/ (* pi 2) 20)) ; may want more than 20
(setq pts '())
(setq ang 0.0)
(repeat 21
(setq pt (polar mp ang rad))
(setq pts (cons pt pts))
(setq ang (+ ang inc))
)

 

 

Posted
9 hours ago, BIGAL said:

Utilicé HatchB.lsp y sí, obtuve una pline como forma definitoria, parece tener dos vértices, así que pude verificarlo y hacer una serie de puntos que serían la pline como facetas.

 

 

 

 

It's interesting
But, at least for me, it doesn't work correctly.
I've drawn a polyline with the points that the function calculates when selecting the yellow circle and this is what I get:

 

Img2-1.png

Posted

And if the hatch has several arcs to compose an irregular shape, it doesn't work well either.
In the following image you can see the perimeter returned by the function when the cyan hatch is selected.

It is interesting to note that all the perimeters returned by the function seem to want to pass through the point 0,0

 

 

Img3.png

Posted

Furthermore, the function in no case returns the inner perimeter

Posted

This should be helpful when you trying something to select inside the CIRCLE (like from attached example file).

 

(setq ent_circle (car (entsel "\nSelect the CIRCLE:"))
      num 50 ;; number of times to repeat inside "repeat" function. Can be changeable, depends of density between the points.
      ang 0.0 ;; default angle
      tot (+ pi pi)
      inc (/ tot (float num))
      cen (cdr (assoc 10 (entget ent_circle))) ;; CIRCLE base point
      rad (cdr (assoc 40 (entget ent_circle))) ;; radius of the CIRCLE
      )
(repeat num
  (setq lst (cons (polar cen ang rad) lst)) ;; creating a LIST with "points" on the CIRCLE
  (setq ang (+ ang inc))
  )
(setq entSelection (ssget "CP" lst '((0 . "LWPOLYLINE")))) ;; make a selection set from previous list of points (lst). SSGET filter can be changed

 

After executing the code, you will get this (picture 1). I changed the color into to the orange, just to make it easier to see all polylines.

 

image.png.d5007e6a477bf1efa71db4b75ba6f6a0.png

 

Maybe the second approach can be also helpful.

 

(setq entOne (car (entsel "\nSelect the first HATCHED area:"))
      objOne (vlax-ename->vla-object entOne)
      )

(vla-getboundingbox objOne 'minPtOne 'maxPtOne) ;; get the boundingbox from hatch

(setq ptMinOne (vlax-safeArray->list minPtOne) ;; get the lower left point
      ptMaxOne (vlax-safeArray->list maxPtOne) ;; get the upper right point
      )

(if (not (tblsearch "LAYER" "TEST_BOUNDARY")) ;; this is just for testing
    (progn
      (command "-layer" "m" "TEST_BOUNDARY" "c" 1 "" "s" "TEST_BOUNDARY" "")
      )
    (progn
      (command "clayer" "TEST_BOUNDARY")
      )
    )

(command-s "_RECTANG" ptMinOne ptMaxOne) ;; make a rectangle to wrap everything around the hatch
(setq entlastOne (entlast)
      objRectangOne (vlax-ename->vla-object entlastOne))

(setq coordsOne (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget entlastOne)))) ;; get the coordinates from previous maded rectangle
(setq ssOutside (ssget "WP" coordsOne '((0 . "LWPOLYLINE")))) ;; make a selection set from previous list of points (coordsOne). SSGET filter can changed

 

After executing the code, you will get this (picture 2). I changed the color into to the orange, just to make it easier to see all polylines and you will se a red rectangle which I get from boundingbox.

 

image.png.a13757f8f14005fbc6263404defd2907.png

 

But if you have this next situation, you can think about changing the "hatch pattern" (something about "ANSI 31"). When you change the "hatch pattern" you can explode it and you will get a bunch o lines. Then, you can create a selection set with filter and then iterate through the loop, and make a new selection set only from lines which are croosing through the "buildings" (picture 3, just an example). You can see how the line will intersect the buildings (red circles), and after the loop was finished, undo everything to get previous "hatch pattern", you will get a new selection set list with buildings who belongs to the hatched area, and than you can iterate through the new selection set to get the data (names) of the buildings.

 

image.thumb.png.a0937d5998e7dcb80f6f6c35f0bc08cb.png

 

I hope it will be helpful, or make a starting point to think about the solution.

Also, tried the Bigals code, but something weird happening, like GLAVCVS say.

 

Best regards.

Posted

Thank you guys for your help.

 

Several comments:

 

Indeed @GLAVCVS, when you get the points of the hatch outline, it always (at least every time I checked) takes the (0 0) points, that's why I remove the first point in "Contours" in my basis code, I do not know why..

 

@Saxlle, thank you for your help, the tip to use ANSI type hatches and explode it is quite intersting!

 

Having the outline points independently of the hatch shape seems very complicated. Even if I make several cases for circles, rectangles et, I can still have hatches like the blue one GLAVCVS told about earlier...

 

11 hours ago, GLAVCVS said:

 

Img3.png

 

I'll try to work on it in the next few days

Posted

You're welcome @Lucay. Than, if you are going to have irregular shapes, than I would think about the 3rd solution which I described, that is going to help you. Maybe something unexpectedly can happend, but let us know if it's happen.

 

Best regards.

Posted (edited)

The problem with the pline being multi objects ars & lines etc. This seemed to work, to get points. Point them on a dummy layer then use ssget, after got points erase the selection set. Yes used HatchB.lsp to make outline.

 

(setvar 'osmode 0)
(setvar 'pdmode 34)

(setq obj (vlax-ename->vla-object (car (entsel "\nPick hatch object "))))

(setq len (vlax-get obj 'length))
(setq inc ( / len 40))
(setq ch 0.0)
(repeat 40 
(setq pt (vlax-curve-getpointatdist obj ch))
(command "point" pt)
(setq ch (+ ch inc))
)

 

Need some real shapes to check properly.

image.png.9b15514fe3facdf5c9b3c64cd7f1d09d.png

Edited by BIGAL
Posted

If you try to run:

 

(vl-cmdf "_hatchedit" (car (entsel "\nSelect HATCH... ")) "_boundary" "_polyline" "_no")


you will generate a perimeter polyline of the selected hatch. It will create polylines for both the outer perimeter and the inner ones, if there are any.
From these polylines, which have arcs, you need to get the list of points

 

 

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...