Looking for help with drawing diamond patterns with lisp

Looking for help with drawing diamond patterns with lisp

annoisscary
Advocate Advocate
891 Views
11 Replies
Message 1 of 12

Looking for help with drawing diamond patterns with lisp

annoisscary
Advocate
Advocate

I am wanting to write a lisp to do diamond lite patterns and the first place to start (in my opinion) would be a formula to evenly size the diamonds no matter the opening. Trying to find the formula to divide space into equal lites, can't find anything on google etc... So the general idea here would be that Instead of just drawing the same pattern everytime, I would specify a number of individual lites, and it would draw them as in the picture. So what I'm really looking for is, if I am aiming for say 31 lites, How can I figure out how many points to draw the lines from? (see picture below)

 

annoisscary_0-1666093188602.png

 

Any help is appreciated, thanks!

0 Likes
892 Views
11 Replies
Replies (11)
Message 2 of 12

Kent1Cooper
Consultant
Consultant

If hor is the number of divisions along the horizontal top/bottom edges, and ver the same for the vertical side edges, and if each corner has a muntin coming out of it as in your image [that is, not these kinds of arrangements:]

Kent1Cooper_0-1666095741994.png

then the number of panes is:

 

(+ (* hor (1+ ver)) (* ver (1+ hor)))

 

So giving it the divisions you can get the resulting number of panes, but going in the other direction may not be feasible, since the numbers play off against each other.

 

Are you really intending to ask for any number of panes?  Your image could get to your 31 by dividing either direction [presumably the vertical edges] into 4 instead of 3, but if you asked for 30, there may not be any combination that will give you that.

 

EDIT:  How about just a chart?  Surely the number of divisions in either direction is not going to be less than 2, nor more than some reasonably low number [maybe something like 8?].  A simple graph could put the number of horizontal divisions across the top and the vertical down the side, and be filled in with the resulting number of panes for each combination, and you could just look for a number you like, and wouldn't try any that can't be done.

Kent1Cooper_1-1666096485727.png

 

Kent Cooper, AIA
0 Likes
Message 3 of 12

annoisscary
Advocate
Advocate

Great solution so far, however you did expand on something I didn't. the patterns could go 1 of 2 ways, either as shown in the picture I provided, or as shown in the first pattern in the example you provided. The chart is a good idea, I was aware some combinations just aren't possible and figured I would either make a list of possible numbers or let it error out.

 

So next question would be, what method could I use to figure out the pattern for the first example you provided?

0 Likes
Message 4 of 12

Kent1Cooper
Consultant
Consultant

@annoisscary wrote:

....what method could I use to figure out the pattern for the first example you provided?


In that situation, with muntins not coming from the corners, if hor is now the number of muntin points along the horizontal top/bottom edges [one fewer than the number of divisions they create, but the divisions are not the same size], and ver the same for the vertical sides, then the number of panes is:

 

(+ (* hor ver) (* (1+ hor) (1+ ver))) 

 

You would presumably use DIVIDE along Line edges with twice the number of muntin points, and use every other resulting Point to draw the muntins from/to.

 

Further EDIT:  Another twist is to use the DIV+ command in DivideMeasurePlus.lsp, >here<.  It has several enhancements/improvements compared to the regular DIVIDE command, one of which is that it gives you the option to put the Points [or Blocks, etc.] at the midpoints of the divisions, rather than the standard of putting them at the division points.  Using that on Line edges, with the desired number of muntin points [not doubled] will give you the Points where you need them, directly.

Kent Cooper, AIA
0 Likes
Message 5 of 12

annoisscary
Advocate
Advocate

Okay so, having a good foundation for figuring out what patterns are possible now, do you have any recommendations on how I would actually draw them? Not asking for you to write it all out or anything, a suggestion would do.

0 Likes
Message 6 of 12

Kent1Cooper
Consultant
Consultant

Is the perimeter to draw them in a Polyline rectangle, or four Lines?  Either way, finding the Point locations along the edges should be doable though challenging.  A routine would need to establish which edges are vertical and which horizontal with some kind of comparison, and apply the right divisions to the right edges.  If a Polyline, it would need to take into account at which corner is starts and in which direction it's drawn.

 

Even more interesting would be the calculation of which locations to connect to which others.  In your image, with equal numbers of divisions in the two directions, Lines go across the diagonally opposite corners -- easy enough as a start.  Then a Line [or Polyline?] would need to start 1/3 of the way from the left end of the bottom edge, find its way to 1/3 of the way down from the top on the right, then 1/3 of the way from the right on the top, etc.  If it was 31 panes in 3Hx4V division, no straight diagonals -- a Line would go from [for example] the bottom left corner to some place along the right edge, and then from there up to a place along the top edge, and from there down to a place along the left edge, etc.  Figuring out those relationships could be difficult, but it may be possible.

 

Here's a cockamamie idea:  How about two User-defined Hatch patterns of parallel lines running in the two angular directions?  A routine could pretty easily use the division numbers and the size of the outline to calculate the angles needed and the spacing, with a little trigonometry.  Origin points would be at corners in your diagram, and non-corner origin points for mine could be calculated pretty easily.

Kent Cooper, AIA
0 Likes
Message 7 of 12

annoisscary
Advocate
Advocate

I had thought of doing hatch patterns, and it might still be an option. But before I get to far into this let me throw another thing into the mix that's going to make this even more of a pain. (lol, sorry.)

 

The fun part about all of this is that the diamonds outline could be basically any overall width. so just to get the ball rolling I've been just using a single segment, which would be the center point for my actually bar. So in reality its going to end up looking like this:

annoisscary_0-1666105375602.png

 

So my thoughts are that yeah, Sometimes a hatch would work if I was drawing something like leaded class for instance. But if I'm drawing anything else its going to be offset from the center line. Now ideally I would draw it all out in a routine, however anything is better than the way we typically draw it. 

 

So again, any ideas? I was thinking I could probably figure out a way to array everything with some trig but I'm the type who honestly doesn't know if its possible until I spend a week trying. As always, any tips appreciated.

0 Likes
Message 8 of 12

annoisscary
Advocate
Advocate

So the pattern above is actually pretty simple when approaching it with a "draw 1 diamond, array it to fill" mentality.

Can just do the division the same as a rectangle pattern. Was trying to research some trig to use to figure out the difference in height and width once its offset, I'll get there eventually I think but no luck as of yet. Was thinking I could maybe "Split" the diamonds into 4 right angle triangles and use one of them to figure out the differences in size, but even assuming I work that out I'm kind of at a loss for how I will draw the quarter/Half diamonds in the corners and on the perimeter. As I'm writing this I'm thinking, maybe a function that draws triangles given a width and height. Anyways, here is where I landed with the first version.

(Defun C:DLP (/
*error*
pt1 pt3 pt2 pt4 xl yl wthht	dpt1


)
;-----------------------------------------------------------------------------------------------
	(defun *error* (msg)
	(if osm (setvar 'osmode osm))
	(and msg(not (wcmatch (strcase msg)"*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
	(princ (strcat "\nError: " msg))
	)
	(if
	(= 8 (logand (getvar 'undoctl) 8))
	(vla-endundomark adoc)
	)
	(setvar "cmdecho" 1)

    (princ)
)
;-----------------------------------------------------------------------------------------------
	(defun DrawDia (ptt1 wth ht / ptt2 ptt3 ptt4) ; draws a Diamond (Rhombus)
	(setq ptt2 (mapcar '+ ptt1 (list (/ wth 2) (/ ht 2) 0.0)))
	(setq ptt3 (mapcar '+ ptt2 (list (-(/ wth 2)) (/ ht 2) 0.0)))
	(setq ptt4 (mapcar '+ ptt3 (list (-(/ wth 2)) (-(/ ht 2)) 0.0)))
	(command "pline" ptt1 ptt2 ptt3 ptt4 "C")
	(princ)
	)
;----------------------------------------------------------------------------------------------- 
  (initget 7)
  (setq xn (getint "\nEnter Number of Columns (W): "))
  (initget 7)
  (setq yn (getint "\nEnter Number of Rows (H): "))
  (setq
		pt1 (getpoint "\nSelect Lower Left Corner: ")
        pt3 (getcorner pt1 "\nSelect Upper Right Corner: ")
        pt2 (list (car pt3) (cadr pt1))
        pt4 (list (car pt1) (cadr pt3))
        xl (distance pt1 pt2)                              
        yl (distance pt1 pt4)
		wth (/ xl xn)
		ht (/ yl yn)
		dpt1 (mapcar '+ pt1 (list (/ wth 2) 0 0))
		)
;-----------------------------------------------------------------------------------------------
	(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
	(vla-startundomark adoc)
	(setq osm (getvar "osmode"))
	(setvar "osmode" 0)
;-----------------------------------------------------------------------------------------------
  (DrawDia dpt1 wth ht)
  (setq ss (ssget "L"))
  (command "-array" ss "" "R" yn xn ht wth)
  	(vla-endundomark adoc)
	(setvar "osmode" osm)
  (princ)
  )
  
  

 

 

0 Likes
Message 9 of 12

Sea-Haven
Mentor
Mentor

Looking at c/l 1st etc Kents left image  the spacing factor is hor  0.5 1 1 1 0.5 Left edge 0.5 1 0.5 then a list join of lines depending on the number of rows and columns.

Similar for right image

SeaHaven_2-1666138698969.png

 

(Lpt1 Tpt1)(Lpt2 Tpt2)

(Bpt1 Tpt3)(Bpt2 Tpt4)

(Bpt3 Rpt1)

Then do reverse maybe mirror ?

 

 

Re offsets I have done something that used trim to make the patterns correctly, need to solve step 1 1st.

 

I have sent a email response also.

 

0 Likes
Message 10 of 12

annoisscary
Advocate
Advocate

Started trying it with lines instead of an array, thought it was going pretty well but the further I get the more problems I run into. the way it is now most number combinations work, albeit with some overlap here or there. but then you get weird ones where it just doesn't work at all. I'm going to keep messing with it but I figured I would share where I'm leaving off for now.

 

**Edit**

 

Deleted old code, didn't like how complicated the original was becoming. Ended up making it more straightforward and used mirror instead of trying to draw from each corner until they met. Works pretty well if I say so myself,  Now I just need to workout a method offset and trim everything up.

Here is what I have so far:

(Defun C:DLP (/
*error*
pt1 pt3 pt2 pt4 xl yl wth  ht


  DrawDia xn yn bdpt1 bdpt2 ldpt1 ldpt2 rdpt1 rdpt2 tdpt1 tdpt2
                adoc osm )
;-----------------------------------------------------------------------------------------------
	(defun *error* (msg)
	(if osm (setvar 'osmode osm))
	(and msg(not (wcmatch (strcase msg)"*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
	(princ (strcat "\nError: " msg))
	)
	(if
	(= 8 (logand (getvar 'undoctl) 8))
	(vla-endundomark adoc)
	)
	(setvar "cmdecho" 1)

    (princ)
)
;----------------------------------------------------------------------------------------------- 
  (initget 7)
  (setq xn (getint "\nEnter Number of Columns (W): "))
  (initget 7)
  (setq yn (getint "\nEnter Number of Rows (H): "))
  (setq
		pt1 (getpoint "\nSelect Lower Left Corner: ")
        pt3 (getcorner pt1 "\nSelect Upper Right Corner: ")
        pt2 (list (car pt3) (cadr pt1))
        pt4 (list (car pt1) (cadr pt3))
        xl (distance pt1 pt2)                              
        yl (distance pt1 pt4)
		mid (mapcar '+ pt1 (list (/ xl 2) (/ yl 2) 0))
		midx (mapcar '+ pt1 (list (/ xl 2) 0 0))
		wth (/ xl xn)
		ht (/ yl yn)
		bdpt1 (mapcar '+ pt1 (list (/ wth 2) 0 0))
		bdpt2 (mapcar '+ pt2 (list (-(/ wth 2)) 0 0))
		ldpt1 (mapcar '+ pt1 (list 0 (/ ht 2) 0))
		ldpt2 (mapcar '+ pt4 (list 0 (-(/ ht 2)) 0))
		rdpt1 (mapcar '+ pt2 (list 0 (/ ht 2) 0))
		rdpt2 (mapcar '+ pt3 (list 0 (-(/ ht 2)) 0))
		tdpt1 (mapcar '+ pt4 (list (/ wth 2) 0 0))
		tdpt2 (mapcar '+ pt3 (list (-(/ wth 2)) 0 0))
		)
;-----------------------------------------------------------------------------------------------
	(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
	(vla-startundomark adoc)
	(setq osm (getvar "osmode"))
	(setvar "osmode" 0)
;-----------------------------------------------------------------------------------------------
	(setq ss (ssadd))
	(setq rpt (-(+ xn yn)2))
	(cond ((= xn yn)
	(setq rpt (-(+ xn yn)1))))
	(repeat rpt
	(if(and(<(cadr ldpt1)(cadr pt4))(<(car bdpt1)(car pt2)))	;Until past top left or bottom right
	(progn
	(entmake(list'(0 . "LINE")'(100 . "AcDbEntity")'(67 . 0)'(8 . "LAYER")'(100 . "AcDbLine")(cons '10 ldpt1)(cons '11 bdpt1)))
	(ssadd (entlast)ss)
	(setq bdpt1 (mapcar '+ bdpt1 (list wth 0 0)))
	(setq ldpt1 (mapcar '+ ldpt1 (list 0 ht 0))))
	)
	(if(and(>(cadr ldpt1)(cadr pt4))(<(car bdpt1)(car pt2))) ;If Past top left but not bottom right
	(progn
	(entmake(list'(0 . "LINE")'(100 . "AcDbEntity")'(67 . 0)'(8 . "LAYER")'(100 . "AcDbLine")(cons '10 tdpt1)(cons '11 bdpt1)))
	(ssadd (entlast)ss)
	(setq bdpt1 (mapcar '+ bdpt1 (list wth 0 0)))
	(setq tdpt1 (mapcar '+ tdpt1 (list wth 0 0))))
	)
	(if(and(>(car bdpt1)(car pt2))(<(cadr ldpt1)(cadr pt4))) ;if past bottom right but not top left
	(progn
	(entmake(list'(0 . "LINE")'(100 . "AcDbEntity")'(67 . 0)'(8 . "LAYER")'(100 . "AcDbLine")(cons '10 ldpt1)(cons '11 rdpt1)))
	(ssadd (entlast)ss)
	(setq rdpt1 (mapcar '+ rdpt1 (list 0 ht 0)))
	(setq ldpt1 (mapcar '+ ldpt1 (list 0 ht 0))))
	)
	(if(and(>(car bdpt1)(car pt2))(>(cadr ldpt1)(cadr pt4))) ;if past both
	(progn
	(entmake(list'(0 . "LINE")'(100 . "AcDbEntity")'(67 . 0)'(8 . "LAYER")'(100 . "AcDbLine")(cons '10 rdpt1)(cons '11 tdpt1)))
	(ssadd (entlast)ss)
	(setq rdpt1 (mapcar '+ rdpt1 (list 0 ht 0)))
	(setq tdpt1 (mapcar '+ tdpt1 (list wth 0 0))))
	)
	)
	(command "Mirror" ss "" mid midx "n")
;-----------------------------------------------------------------------------------------------
  	(vla-endundomark adoc)
	(setvar "osmode" osm)
  (princ)
  )
  
  

 

 

0 Likes
Message 11 of 12

Sea-Haven
Mentor
Mentor

Been in touch and possible final result, will let annoisscary post final code.

 

SeaHaven_0-1666230638409.png

 

0 Likes
Message 12 of 12

annoisscary
Advocate
Advocate

Alright! We got everything working as it should be, for kicks I tested up to 60x60 offset patterns and while it did take a second to run it drew it perfectly!

Thanks to @Sea-Haven the offsets are cleaned up nicely and no manual intervention is needed. Along with the addition of his code I added the option to pick an offset or just draw the pattern centerline style.

 

 

 

P.S.

Decided to focus on 1 pattern as this is the most likely case scenario.

0 Likes