Issue trimming rebar mesh with LISP routine for non-rectangular slabs

Issue trimming rebar mesh with LISP routine for non-rectangular slabs

rsalastopografia
Advocate Advocate
714 Views
22 Replies
Message 1 of 23

Issue trimming rebar mesh with LISP routine for non-rectangular slabs

rsalastopografia
Advocate
Advocate

Hi everyone,

I'm using a LISP routine that generates a rebar mesh inside a concrete slab, based on a closed polyline or a circle. The script asks for a cover distance and spacing, creates an inward offset, and then draws horizontal and vertical bars that should be trimmed to fit within the offset boundary.

The routine works perfectly when the slab is a rectangle (see image 1), but when using irregular, circular, or triangular shapes, the bars are not trimmed properly (see image 2). Full-length bars are drawn, ignoring the actual shape of the slab.

rsalastopografia_0-1751672463426.png

Figura 1

rsalastopografia_1-1751672488346.png

Figura 2

The trimming is done using IntersectWith, but I believe the code assumes there are always exactly two intersection points per bar, which doesn't hold true for more complex shapes.

Any guidance on how to adapt the routine so that it works with any closed polyline, regardless of shape, would be greatly appreciated.

Thanks in advance!

(Images attached)

Attached lisp and dwg file

0 Likes
Accepted solutions (2)
715 Views
22 Replies
Replies (22)
Message 2 of 23

Sea-Haven
Mentor
Mentor

 

Ok 1st part over draw your bars so they cover the entire shape. Which it looks like you have done.

Do an offset of outside shape, so you now have an inside cut line for trim. Save ent name using (entlast)

Offset again inside 1/2 the edge offset, then get all the points of that pline. Erase this middle pline. Again (entlast)

Using Trim you use the 1st offset line as the cut line

Then use (command "trim" plent "" "F" Pts "")

Erase 1st inside offset pline

 

Hopefully that makes sense

You may want this

(setq plent (entlast))

(setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget plent))))
(setq co-ord (cons (last co-ord) co-ord)) ; need to close the points add last again

I will let you do the offset bit in lisp.

0 Likes
Message 3 of 23

rsalastopografia
Advocate
Advocate

Thank you for your response.

In image 02, the goal is to automatically generate a reinforcement mesh within concrete slabs of irregular geometry (circle, triangle, trapezoid, etc.), based on both the concrete cover and the defined bar spacing.

Additionally, the mesh bars should be trimmed to the inner boundary of the slab (that is, the offset generated by the concrete cover), and this entire process is expected to be fully automated using a LISP routine, without manual intervention or the use of commands like TRIM.

Does help retrieve the vertex coordinates of the last generated polyline (usually the offset). This could be useful if those points are to be used as trimming references. However, by itself, this snippet does not solve the automatic trimming of the mesh bars, nor does it guarantee proper adjustment in non-rectangular shapes.

In summary, your approach may contribute as part of a broader solution, but it does not, on its own, fulfill the goal of full automation that is being pursued with this LISP routine.

 

0 Likes
Message 4 of 23

Sea-Haven
Mentor
Mentor

Did you have a go ?

 

Yes it works, used the method many times over the years tested manually on your sample dwg. I just did not do any code. Sometimes a verbal solution is provided and that is a hint to have a go at writing the code. Do you know about using Fence option with TRIM ?

 

Your shape using this method, just done manually. Just erase dummy cover shape.

SeaHaven_0-1751787265408.png

 

You need a different method for the circle working out trim points but can get a very close result.

 

0 Likes
Message 5 of 23

rsalastopografia
Advocate
Advocate

Could you please provide me with the complete code? 

The purpose of the Lisp routine is to automate the entire process without performing manual steps.

0 Likes
Message 6 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia  hi,

 

Check this MESH-TRIM command, it is based on (LM:intersections) function from the greate mr Lee Mac - thank you Lee 👍

 

Command: MESH-TRIM <enter>

Select object(s):  <Select multiple boundary (plines & circles) must be closed>

 

that's all 😀

 

The program now iterate over selection at each running "_CP" crossing polygon on each to select the crossing lines and 'trim' them? no i preferred to draw a new pline over and delete the source (much easier)

 

the challenge here is of course the plines that are crossing at one side (the other inside boundary)

to identify the part inside.

 

enjoy,

Moshe

 

 

(vl-load-com)

;; Intersections  -  Lee Mac
;; Returns a list of all points of intersection between two objects
;; for the given intersection mode.
;; ob1,ob2 - [vla] VLA-Objects
;;     mod - [int] acextendoption enum of intersectwith method

(defun LM:intersections ( ob1 ob2 mod / lst rtn )
    (if (and (vlax-method-applicable-p ob1 'intersectwith)
             (vlax-method-applicable-p ob2 'intersectwith)
             (setq lst (vlax-invoke ob1 'intersectwith ob2 mod))
        )
        (repeat (/ (length lst) 3)
            (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn)
                  lst (cdddr lst)
            )
        )
    )
    (reverse rtn)
); LM:intersections


(defun c:mesh-trim (/ isObjValid _geometric get_centroid isOneSegCurve draw_line draw_pline add_new_bar ; local functions
		      adoc modelSpace ss0 ename0 elist0 ss1 c0 AcDbPLine0 ename1 Rent        ; local variables
		      AcDbObj1 layName cross^ t0 t1 ent0 ent1 lst0 lst1 AcDbLine0 AcDbLine1) ; local variables

 (defun isObjValid (edata)
  (cond
   ((eq (cdr (assoc '0 edata)) "CIRCLE")
    T
   ); case
   ((eq (cdr (assoc '0 edata)) "LWPOLYLINE")
    (if (= (logand (cdr (assoc '70 edata)) 1) 1)
     T
     (progn
      (vlr-beep-reaction)
      (prompt "\nunclosed boundary is rejected.")
     ); progn
    ); if
   ); case
  ); cond
 ); isObjValid


 (defun _geometric (edata / c0 r0 a0 m n i pts^)
  (if (eq (cdr (assoc '0 edata)) "CIRCLE")
   (progn
    (setq c0 (cdr (assoc '10 edata)))
    (setq r0 (cdr (assoc '40 edata)))

    (setq i 0 a0 0.0 m (/ pi 18))
    (repeat 36
     (setq i (1+ i) a0 (* i m))
     (setq pts^ (cons (polar c0 a0 r0) pts^))
    ); repeat
    (reverse pts^)
   ); progn
   ; for plines
   (mapcar 'cdr (vl-remove-if-not (function (lambda (e) (= (car e) 10))) edata))
  ); if
 ); _geometric

  
 (defun get_centroid (ename / AcDbPline sa curves objList array AcDbRegion c0)
  (setq AcDbEntity (vlax-ename->vla-object ename))

  (cond
   ((eq (vla-get-objectName AcDbEntity) "AcDbCircle")
    (setq c0 (vlax-safearray->list (vlax-variant-value (vla-get-center AcDbEntity))))
   ); case
   ((eq (vla-get-objectName AcDbEntity) "AcDbPolyline")
    (setq sa (vlax-make-safearray vlax-vbObject '(0 . 0)))
    (setq curves (vlax-safearray-fill sa (list AcDbEntity)))
    (setq objList (vla-addRegion modelSpace curves))
    (setq array (vlax-safearray->list (vlax-variant-value objList)))
    (setq AcDbRegion (nth 0 array))
    (setq c0 (vlax-safearray->list (vlax-variant-value (vla-get-centroid AcDbRegion))))
    (vla-delete AcDbRegion)
    (vlax-release-object AcDbRegion)
   ); case
  ); cond

  (vlax-release-object AcDbEntity)
  c0
 ); get_centroid

  
 (defun isOneSegCurve (ent / edata)
  (setq edata (entget ent))
  (cond
   ((eq (cdr (assoc '0 edata)) "LINE")
    t
   ); case
   ((eq (cdr (assoc '0 edata)) "LWPOLYLINE")
    (= (setq n (vlax-curve-getParamAtPoint ent (vlax-curve-getEndPoint ent))) 1.0)
   ); case
  ); cond
 ); isOneSegCurve

  
 (defun draw_line (t0 t1 lay)
  (entmakex
   (list
    '(0 . "LINE")
    '(100 . "AcDbLine")
    (cons '8 lay)
    (cons '10 t0)
    (cons '11 t1)
   ); list
  ); entmakex
 ); draw_line
  
  
 (defun draw_pline (pts^ val lay / pt)
  (entmakex
   (append
     (list '(0   . "LWPOLYLINE")
           '(100 . "AcDbEntity")
           '(100 . "AcDbPolyline")
	    (cons '8 lay)
            (cons '90 (length pts^))
	    (cons '70 val)
     )
     (mapcar
      '(lambda (pt)
        (cons '10 pt)
       )
       pts^
     ); mapcar
   ); append
  ); entmake
 ); draw_pline

  
 ; here start c:mesh-trim
 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startUndoMark adoc)
  
 (setq modelSpace (vla-get-modelspace adoc))

 (if (setq ss0 (ssget '((0 . "circle,lwpolyline")))) ; select multiple boundaries
  (foreach ename0 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss0)))
   (setq elist0 (entget ename0))

   (if (and
	 (isObjValid elist0) ; is pline closed?
         (setq ss1 (ssget "_cp" (_geometric elist0) '((0 . "line,lwpolyline"))))
       )
    (progn
     (if (ssmemb ename0 ss1)
      (ssdel ename0 ss1)
     )

     (setq c0 (get_centroid ename0))
     (setq AcDbPLine0 (vlax-ename->vla-object ename0))

     (foreach ename1 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss1)))
      (setq Rent nil)
      (setq AcDbObj1 (vlax-ename->vla-object ename1)) ; circle or pline
      (setq layName (vla-get-layer AcDbObj1))

      (if (and
	    (isOneSegCurve ename1) ; is it one segment?
	    (setq cross^ (LM:intersections AcDbPLine0 AcDbObj1 acExtendNone)) ; has intersections
	  )
       (cond
        ((= (vl-list-length cross^) 2)
         (setq Rent (draw_pline cross^ 0 layName))
        ); case
        ((= (vl-list-length cross^) 1)
         (setq t0 (vlax-curve-getStartPoint ename1))
         (setq t1 (vlax-curve-getEndPoint ename1))

         (setq ent0 (draw_line c0 t0 layName))
         (setq AcDbLine0 (vlax-ename->vla-object ent0))
         (setq lst0 (LM:intersections AcDbPLine0 AcDbLine0 acExtendNone))
       
         (setq ent1 (draw_line c0 t1 layName))
         (setq AcDbLine1 (vlax-ename->vla-object ent1))
         (setq lst1 (LM:intersections AcDbPLine0 AcDbLine1 acExtendNone))

         (cond
	  ((and
	      lst1
	      (= (rem (vl-list-length lst1) 2) 1)
	   )
           (setq Rent (draw_pline (list t0 (car cross^)) 0 layName))
          ); case
	  ((and
	      lst0
	      (= (rem (vl-list-length lst0) 2) 1)
	   )
           (setq Rent (draw_pline (list t1 (car cross^)) 0 layName))
          ); case
         ); cond
       
         (vla-delete AcDbLine1)
         (vlax-release-object AcDbLine1)
       
         (vla-delete AcDbLine0)
         (vlax-release-object AcDbLine0)
        ); case
       ); cond
      ); if

      (if Rent
       (vla-delete AcDbObj1)
      )
     
      (vlax-release-object AcDbObj1)
     ); foreach

     (vlax-release-object AcDbPLine0)
    ); progn
   ); if
    
  ); foreach
 ); if

 (vlax-release-object modelSpace)

 (vla-endUndoMark adoc)
 (vlax-release-object adoc)
  
 (princ)
); c:mesh-trim

 

 

 

0 Likes
Message 7 of 23

Sea-Haven
Mentor
Mentor

Another, but make sure the bars extend out side the shape.

 

(defun c:trimreo ( / co-ord cover dist ent2 ent3 oldsnap plent ptc)
  (setq oldsnap (getvar 'osmode))
  (setvar 'osmode 0)
  (setq plent (car (entsel "\pick pline ")))
(setq ptc (getpoint "\nPick a point inside shape "))
  (setq cover (getreal "\nEnter edge cover "))
    (command "offset" cover plent ptc "")
  (setq ent2 (entlast))
  (setq dist (- cover 0.001))
  (command "offset" dist plent ptc "")
  (setq ent3 (entlast))
  (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent3))))
  (setq co-ord (cons (last co-ord) co-ord))
  (command "erase" ent3 "")
  (command "trim" ent2 "" "f" co-ord "" "")
  (command "erase" ent2 "")
  (setvar 'osmode oldsnap)
  (princ)
)
(c:trimreo)
0 Likes
Message 8 of 23

rsalastopografia
Advocate
Advocate

Your code is very interesting and solves several problems. I managed to merge it into a single routine that draws the steel layout in a plant with different polygons, and it looks like this:

;;; Rutina fusionada y optimizada: Generación de malla con recorte automático para losas
;;; Autor: Adaptación basada en rutinas anteriores
;;; Requiere: Círculo o polilínea cerrada como contorno de losa

(vl-load-com)

(defun LM:intersections (ob1 ob2 mod / lst rtn)
(if (and (vlax-method-applicable-p ob1 'intersectwith)
(vlax-method-applicable-p ob2 'intersectwith)
(setq lst (vlax-invoke ob1 'intersectwith ob2 mod)))
(repeat (/ (length lst) 3)
(setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn)
lst (cdddr lst)))
)
(reverse rtn))

(defun crear-capa (nombre color)
(if (not (tblsearch "LAYER" nombre))
(command "_.LAYER" "_Make" nombre "_Color" color nombre "")
)
)

(defun obtener-offset-seguro (obj rec / offsetObjs)
;; Intenta generar offset hacia adentro usando rec negativo
(setq offsetObjs (vlax-invoke obj 'Offset (- (abs rec))))
(if offsetObjs
(car offsetObjs)
nil))

(defun c:MALLA-LOSA-FUSIONADA (/ ent obj tipo rec esp minPt maxPt minX maxX minY maxY x y p1 p2 todasVarillas offsetObj offsetEnt puntos pt1 pt2
adoc modelSpace objV lst countX countY intersectList capa)
(prompt "\nSeleccione la polilínea cerrada o círculo que representa la losa: ")
(setq ent (car (entsel)))
(if (not ent)
(progn (prompt "\nNo se seleccionó ninguna entidad.") (exit)))

(setq obj (vlax-ename->vla-object ent)
tipo (vla-get-objectname obj))

(cond
((and (= tipo "AcDbPolyline") (= (vla-get-Closed obj) :vlax-true)))
((= tipo "AcDbCircle"))
(T (prompt "\nERROR: La entidad no es una polilínea cerrada ni un círculo.") (exit)))

(setq rec (getreal "\nIndique el recubrimiento [m]: "))
(setq esp (getreal "\nIndique el espaciamiento entre varillas [m]: "))

;; Crear capas
(crear-capa "A_MALLA_X" 1)
(crear-capa "A_MALLA_Y" 3)
(crear-capa "A_OFFSET" 6)

;; Offset hacia adentro
(setq offsetObj (obtener-offset-seguro obj rec))
(if (null offsetObj)
(progn (prompt "\nERROR: No se pudo generar offset hacia adentro.") (exit)))

(setq offsetEnt (vlax-vla-object->ename offsetObj))
(entmod (subst (cons 8 "A_OFFSET") (assoc 8 (entget offsetEnt)) (entget offsetEnt)))
(vla-put-color offsetObj 6)

;; Bounding box del offset
(vla-GetBoundingBox offsetObj 'minPt 'maxPt)
(setq minPt (vlax-safearray->list minPt)
maxPt (vlax-safearray->list maxPt)
minX (car minPt) maxX (car maxPt)
minY (cadr minPt) maxY (cadr maxPt))

(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
(setq modelSpace (vla-get-modelspace adoc))

(setq todasVarillas '() countX 0 countY 0)

;; Horizontales
(setq y minY)
(while (<= y maxY)
(setq p1 (list minX y 0.0) p2 (list maxX y 0.0))
(setq objV (vla-addLine modelSpace (vlax-3D-point p1) (vlax-3D-point p2)))
(vla-put-layer objV "A_MALLA_X")
(setq intersectList (LM:intersections offsetObj objV acExtendNone))
(if (= (length intersectList) 2)
(progn
(vla-delete objV)
(setq objV (vla-addLine modelSpace (vlax-3D-point (nth 0 intersectList))
(vlax-3D-point (nth 1 intersectList))))
(vla-put-layer objV "A_MALLA_X")
(setq countX (1+ countX))
)
(vla-delete objV))
(setq y (+ y esp)))

;; Verticales
(setq x minX)
(while (<= x maxX)
(setq p1 (list x minY 0.0) p2 (list x maxY 0.0))
(setq objV (vla-addLine modelSpace (vlax-3D-point p1) (vlax-3D-point p2)))
(vla-put-layer objV "A_MALLA_Y")
(setq intersectList (LM:intersections offsetObj objV acExtendNone))
(if (= (length intersectList) 2)
(progn
(vla-delete objV)
(setq objV (vla-addLine modelSpace (vlax-3D-point (nth 0 intersectList))
(vlax-3D-point (nth 1 intersectList))))
(vla-put-layer objV "A_MALLA_Y")
(setq countY (1+ countY))
)
(vla-delete objV))
(setq x (+ x esp)))

(prompt (strcat
"\n✔ Malla generada correctamente:"
"\n → " (itoa countX) " varillas horizontales"
"\n → " (itoa countY) " varillas verticales"
"\n → Total: " (itoa (+ countX countY)) " varillas."
"\n → Offset generado hacia adentro en capa A_OFFSET (magenta).\n"))
(princ))

 

Everything works perfectly, with the only drawback being that the offset (representing the steel cladding) is generated outwards with respect to the polygon that represents the concrete structure.

rsalastopografia_0-1751907928357.png

In Figure 1, the black polyline is the concrete structure, and the magenta one is the steel cladding. We notice that the magenta polyline is located outside the slab polyline, when it should actually be placed inward, and the steel layout should be trimmed from there. Could you please help me improve this code so it works correctly? The distribution of the steel mesh of the polygons should be as shown in the circle (steel coating inside the figure)

0 Likes
Message 9 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia ,

 

if you draw the black pline and than the magenta pline inward 0.05m and run MESH-TRIM and select the magenta pline

it will be trimmed on the magenta pline - isn't that want you want?

 

or

 

you draw only the black pline and want the trim to be further inward 0.05m trimmed?

 

 

0 Likes
Message 10 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia ,

 

test it and it does not work good, better draw the 2 plines and select the one on which you want the trim.

0 Likes
Message 11 of 23

rsalastopografia
Advocate
Advocate

The objective of this routine is to automate the entire process. When selecting an entity (a polygon representing a concrete structure), it must generate the steel mesh distribution, taking into account the steel cover and steel spacing. In polygons, the offset is being generated externally, which is incorrect, while in circles, the offset is generated correctly to then distribute the steel mesh correctly within that entity. I want this process to run for any polygon; it may require some code changes; the routine is working well for more than 90%.

0 Likes
Message 12 of 23

Sea-Haven
Mentor
Mentor

A similar problem is concrete waffle slabs where you need to place the waffles for any shape. So to get around the problem I pick 2 points well outside the internal shape then the bars would be drawn exceeding the shape based on the limits defined by the 2 points. Then you can trim inside the shape, ok now giving away the method you find all objects inside the outer shape and put them on a dummy layer and turn off, you delete remaining line work out side the shape, then change the dummy layer back to correct layer and display. The other thing in my code is that you pick a seed point for the start of the bars, then array them.

 

SeaHaven_1-1751941040873.png

 

 

0 Likes
Message 13 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia ,

 

Sorry  😂 looks like i was not a ware of the all process (thought all you want is to trim on a polygon)

so to bring me to 'business' would you please summarize for me the all process.

 

write down the all steps we need, it would help if you also post a sample dwg with before and after.

if the routine also add the mesh bars, can it be done with hatch?

 

Moshe

 

0 Likes
Message 14 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia ,

 

ok i started to understand what you want here and it is much simple then what i have done

tonight i will fix it 😀

 

Moshe

 

0 Likes
Message 15 of 23

Moshe-A
Mentor
Mentor
Accepted solution

@rsalastopografia hi,

 

This one called MALLA, done with HATCH command and no need to trim anything 😀

if you like, the hatch can be explode. hatch origin is set to Centroid of polygon. tell me if you want something else?

 

works?

Moshe

 

 

(vl-load-com)

(defun c:malla (/ initial askreal make_data_layers get_centroid is_smaller _swapVar ; local functions
		  DATA_LAYERS adoc modelSpace defOset defNetx oset netx ss0 ename0 ename1 obj1^ obj2^ AcDbObj0 AcDbObj1 AcDbObj2)

 (defun initial ()
  ; const
  (setq DATA_LAYERS '(("A_MALLA_X" . 1) ("A_MALLA_Y" . 3) ("A_OFFSET" . 6)))

  (if (= (getvar "userr4") 0.0)
   (setq defOset (setvar "userr4" 0.05))
   (setq defOset (getvar "userr4"))
  )
 
  (if (= (getvar "userr5") 0.0)
   (setq defNetx (setvar "userr5" 0.20))
   (setq defNetx (getvar "userr5"))
  )
 ); initial
  
 (defun askreal (msg def / ask)
  (initget (+ 2 4))
  (if (not (setq ask (getreal (strcat "\n" msg " <" (rtos def 2) ">: "))))
   (setq ask def)
   (setq def ask)
  )
 ); askreal


 (defun make_data_layers ()
  (foreach data DATA_LAYERS
   (if (null (tblsearch "layer" (car data)))
    (command "._layer" "_New" (car data) "_Color" (cdr data) (car data) "")
   ); if
  ); foreach
 ); make_data_layers

  
 (defun get_centroid (ent / edata AcDbPline curves obj^ c0)
  (setq edata (entget ent))

  (cond
   ((eq (cdr (assoc '0 edata)) "CIRCLE")
    (setq c0 (cdr (assoc '10 edata)))
   ); case
   ( t
    (setq AcDbPline (vlax-ename->vla-object ent))
    (setq curves (vlax-make-safearray vlax-vbObject '(0 . 0)))
    (vlax-safearray-put-element curves 0 AcDbPline)
    (setq obj^ (vlax-safearray->list (vlax-variant-value (vla-AddRegion modelSpace curves))))
    (setq c0 (vlax-safearray->list (vlax-variant-value (vla-get-centroid (car obj^)))))

    (foreach o obj^
     (vla-delete o)
     (vlax-release-object o)
    )
    
    (vlax-release-object AcDbPline)
    c0
   ); case
  ); cond
 ); get_centroid

 ; anonymous function
 (setq is_smaller (lambda (o1 o2) (< (vla-get-area o1) (vla-get-area o2))))

 ; swap variable
 (defun _swapVar (Qa0 Qa1 / tmp)
  (setq tmp (vl-symbol-value Qa0))
  (set  Qa0 (vl-symbol-value Qa1))
  (set  Qa1 tmp)
 ); _swapVar

   
 ; here start c:mesh-trim
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")

 (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
 (setq modelSpace (vla-get-modelspace adoc))

 (initial) ; data defaults

 (if (and
        (setvar "userr4" (setq oset (askreal "Offset cover" defOset)))
        (setvar "userr5" (setq netx (askreal "Net interval" defNetx)))
        (setq ss0 (ssget '((0 . "lwpolyline,circle"))))
      )
  (progn
   (make_data_layers)
   
   (foreach ename0 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss0)))
    (setq AcDbObj0 (vlax-ename->vla-object ename0))

    (setq obj1^ (vlax-safearray->list (vlax-variant-value (vla-offset AcDbObj0 (*  1.0 oset)))))
    (setq obj2^ (vlax-safearray->list (vlax-variant-value (vla-offset AcDbObj0 (* -1.0 oset)))))

    (if (not (is_smaller (car obj1^) (car obj2^)))
     (_swapvar 'obj1^ 'obj2^)
    )

    (setq ename1 (vlax-vla-object->ename (car obj1^)))
    (setq AcDbObj2 (car obj2^))
   
    (vla-put-layer AcDbObj2 "A_OFFSET")
    (setq c0 (get_centroid ename1)) 

    (command "._-hatch" "_Layer" "A_MALLA_X" "_Origin" "_set" c0 "_Yes" "_Advanced" "_Associativity" "_No" "" "_Properties" "_U" 0 netx "_No" "_Select" "_si" ename1 "")
    (command "._-hatch" "_Layer" "A_MALLA_Y" "_Properties" "_U" 90 netx "_No" "_Select" "_si" ename1 "")

    (foreach o obj1^
     (vla-delete o) 
     (vlax-release-object o)
    )
    
    (foreach o obj2^ 
     (vlax-release-object o)
    )
    
    (vlax-release-object AcDbObj0)
   ); foreach
  ); progn
 ); if

 (vlax-release-object modelSpace)
 (vlax-release-object adoc)

 (command "._undo" "_end")
 (setvar "cmdecho" 1)
  
 (princ)
); c:malla

 

 

Message 16 of 23

rsalastopografia
Advocate
Advocate

Thanks for solving the problem. This Lisp routine works perfectly and adjusts to any geometry. Best regards.

0 Likes
Message 17 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia hi,

 

thank you for that 😀

 

As you can see it is done with 2 hatches as i separate them with 2 layers for the Hor\Ver lines but it could be done

with one hatch one layer if you want?

 

i may do some more fine tunings to make cleaner.

 

Moshe

 

 

 

Message 18 of 23

Moshe-A
Mentor
Mentor

@rsalastopografia  hi,

 

found a minor bug and fixed it

 

i tried to make it run faster by adding the hatch with activex calls but it turns out even i set the origin point (centroid)

the hatch start with some offset from that point - so i give it up 😀

 

enjoy,

Moshe

 

 

Message 19 of 23

Sea-Haven
Mentor
Mentor

@Moshe-A good idea about using hatch. But occasionally the reo  bars in hor and ver can be different sizes and different spacing. Yes hatch has a few odd ways it works. it may be worth while setting the hatch origin to a point near a corner so the cover offset is taken into account, as mentioned above a seed point. Here in Aus we have reo sheets that different bar sizes hor & ver, and spacing 200 & 100mm 

0 Likes
Message 20 of 23

Moshe-A
Mentor
Mentor

@Sea-Haven ,

 

About hatch origin i did explore it deeply and it turns out that using ActiveX (vla-add hatchObj) only complies with 0,0,0 of the current UCS

in early days i recall that setting SNAPBASE was also a way to change the origin of hatch - good old days 😀

so i did replace the (command ".hatch") calls to fully ActiveX (works very fast now 😀) and add the option to set Hor/Ver lines

separately and will publish it if @rsalastopografia wants?

 

Moshe

 

 

0 Likes