Jump to content

Strick Tower Lisp


Sambuddy

Recommended Posts

So basically this routine is creating a 3D stick model of a tower with specified segment height (that is the portion between each horizontal line), and connects the lines based on the base width and highest elevation width to form a trapazoidal/ conical shape as it graduates upward and in 2 flavours (3 legged and 4 legged supports). 

I cannot figure out the following no matter how much I tried:

1) I need to create a spacing between the diagonal bracings and the horizontal lines so that is user specified. Right now, every origin of the diagonal bracing starts at the end of the horizontal line. In some scenrios this is alright, but in many, i would need a vertical spacing of a user specified value to seperate the two as whon on my second photo.

2) The concept in general is wrong, as the number of segments should constitute the segments on the assembly that can be welded or bolted to bring to the site, what I have right now is small segments that will makeup the assembly but the tapared "main legs" should not be separated or broken (currently each segment is drawn to the point of intersecting with the next horizontal line). I would like to have "Assembly height" and then devise them into as many segments that makeup that portion on the assembly.

3) I would have liked to then (with #2 resolved) have the ability to chose what pattern bracing type I want for the next assembly (K/X/Z) onwards.

4) In VBA excel, with the help of simple graph, I can simulate what the tower would look like, and I am not sure if DCL and slides give me the preview (last photo is the userform in VBA, but I abandoned that idea and moved to lisp instead)

I apologize in advance if I did not comment the lisp as much as I should have, but instead used a long variable name to describe the function/ variable

I am sharing my thoughts and hopefully, you all wise people can share yours to solve my issues.

image.png.8c9dea8e48cde64bd466f71163c7b924.png

 

image.thumb.png.e3f91fd17b50e5d6cd9c6dad6a1dd51a.png

image.png.a0eca8e1887e7c9a9e267b49c442f693.png

image.png.878c099faa584643b5b05fa3bb985be8.png

(defun c:TOWER (/ draw-line draw-segment
                 base-corners top-corners current-base-width current-top-width current-height
                 original-ucs original-ortho original-osmode original-cecolor error-handler option shape
                 base-width top-width num-segments segment-height
	       )
  ;; Prompt user for tower dimensions and number of segments
  (or base-width (setq base-width 8000.0))
  (setq base-width
        (cond ((getdist (strcat "\nEnter Base Width " (strcat "< " (rtos base-width 2 3) " > :"))))
              (base-width)))

  (or top-width (setq top-width 4000.0))
  (setq top-width
        (cond ((getdist (strcat "\nEnter Top Width " (strcat "< " (rtos top-width 2 3) " > :"))))
              (top-width)))

  (or num-segments (setq num-segments 10))
  (setq num-segments
        (cond ((getint (strcat "\nEnter Number of Segments " (strcat "< " (rtos num-segments 2 0) " > :"))))
              (num-segments)))

  (or segment-height (setq segment-height 30480.0))
  (setq segment-height
        (cond ((getdist (strcat "\nEnter Total Tower Height " (strcat "< " (rtos segment-height 2 3) " > :"))))
              (segment-height)))

  (setq segment-height (/ segment-height num-segments))

  ;; Prompt user for shape type (4-sided or 3-sided)
  (initget "4 3")
  (setq shape (getkword "\nChoose Tower Geometry : [4/3]: "))

  ;; Prompt user for bracing type
  (initget "K X Z")
  (setq option (getkword "\nChoose Bracing Type : [K/X/Z]: "))

  ;; Save original settings
  (setq original-ortho (getvar 'orthomode))
  (setq original-osmode (getvar 'osmode))
  (setq original-cecolor (getvar 'CECOLOR))

  ;; Error handler to restore settings
  (defun error-handler (msg)
    (if (not (wcmatch (strcase msg) "*CANCEL*,*EXIT*"))
      (princ (strcat "\nError: " msg)))
    (if (numberp original-ortho) (setvar 'orthomode original-ortho))
    (if (numberp original-osmode) (setvar 'osmode original-osmode))
    (if original-cecolor (setvar 'CECOLOR original-cecolor))
    (princ)
  );end defun

  ;; Set UCS to World, Ortho to Off, and Object Snap to None or else it will fuck up the alignment
  (command "._ucs" "_world")
  (setvar 'orthomode 0)
  (setvar 'osmode 0)

  ;; Function to draw a line in 3D
  (defun draw-line (start end)
    (command "LINE" (list (nth 0 start) (nth 1 start) (nth 2 start)) (list (nth 0 end) (nth 1 end) (nth 2 end)) "")
  );end defun
  
  ;; Function to interpolate between two points
  (defun interp-coords (pt1 pt2 factor)
    (mapcar '(lambda (a b) (+ a (* factor (- b a)))) pt1 pt2))
  
  ;; Function to draw a trapezoid segment (4-SIDED)
  (defun draw-segment-4 (base-corners top-corners)
    (setvar 'CECOLOR "24")
    (mapcar 'draw-line base-corners top-corners)
    (mapcar 'draw-line
            base-corners
            (append (cdr base-corners) (list (car base-corners))))
    (mapcar 'draw-line
            top-corners
            (append (cdr top-corners) (list (car top-corners))))
  );end defun

  ;; Function to draw a triangular segment (3-SIDED)
  (defun draw-segment-3 (base-corners top-corners)
    (setvar 'CECOLOR "24")
    (mapcar 'draw-line base-corners top-corners)
    (mapcar 'draw-line
            base-corners
            (append (cdr base-corners) (list (car base-corners))))
    (mapcar 'draw-line
            top-corners
            (append (cdr top-corners) (list (car top-corners))))
  );end defun

  ;; Function 4-sided tower bracing
  (defun draw-additional-lines-4 (base-corners top-corners option)
    (setvar 'CECOLOR "11")
    (cond
      ((equal option "K")
       (progn
         (draw-line (nth 0 base-corners) (interp-coords (nth 0 top-corners) (nth 1 top-corners) 0.5))
         (draw-line (nth 1 base-corners) (interp-coords (nth 1 top-corners) (nth 2 top-corners) 0.5))
         (draw-line (nth 2 base-corners) (interp-coords (nth 2 top-corners) (nth 3 top-corners) 0.5))
         (draw-line (nth 3 base-corners) (interp-coords (nth 3 top-corners) (nth 0 top-corners) 0.5))
         ;; Mirror lines to complete the K option pattern
         (draw-line (nth 0 base-corners) (interp-coords (nth 0 top-corners) (nth 3 top-corners) 0.5))
         (draw-line (nth 1 base-corners) (interp-coords (nth 1 top-corners) (nth 0 top-corners) 0.5))
         (draw-line (nth 2 base-corners) (interp-coords (nth 2 top-corners) (nth 1 top-corners) 0.5))
         (draw-line (nth 3 base-corners) (interp-coords (nth 3 top-corners) (nth 2 top-corners) 0.5))))
      ((equal option "X")
       (progn
         ;; Draw the X pattern on each exterior face
         ;; Face 1
         (draw-line (nth 0 base-corners) (nth 1 top-corners))
         (draw-line (nth 1 base-corners) (nth 0 top-corners))
         ;; Face 2
         (draw-line (nth 1 base-corners) (nth 2 top-corners))
         (draw-line (nth 2 base-corners) (nth 1 top-corners))
         ;; Face 3
         (draw-line (nth 2 base-corners) (nth 3 top-corners))
         (draw-line (nth 3 base-corners) (nth 2 top-corners))
         ;; Face 4
         (draw-line (nth 3 base-corners) (nth 0 top-corners))
         (draw-line (nth 0 base-corners) (nth 3 top-corners))))
      ((equal option "Z")
       (progn
         ;; Add lines to create the Z bracing pattern
         (draw-line (nth 0 base-corners) (nth 1 top-corners))
         ;;Reverse (draw-line (nth 1 base-corners) (nth 2 top-corners))
	 (draw-line (nth 2 base-corners) (nth 1 top-corners))
         ;;Reverse (draw-line (nth 2 base-corners) (nth 3 top-corners))
	 (draw-line (nth 3 base-corners) (nth 2 top-corners))
         (draw-line (nth 3 base-corners) (nth 0 top-corners)))))
  );end defun

  ;; Function 3-sided tower bracing
  (defun draw-additional-lines-3 (base-corners top-corners option)
    (setvar 'CECOLOR "11")
    (cond
      ((equal option "K")
       (progn
         (draw-line (nth 0 base-corners) (interp-coords (nth 0 top-corners) (nth 1 top-corners) 0.5))
         (draw-line (nth 1 base-corners) (interp-coords (nth 1 top-corners) (nth 2 top-corners) 0.5))
         (draw-line (nth 2 base-corners) (interp-coords (nth 2 top-corners) (nth 0 top-corners) 0.5))
         ;; Mirror lines to complete the K option pattern
         (draw-line (nth 0 base-corners) (interp-coords (nth 0 top-corners) (nth 2 top-corners) 0.5))
         (draw-line (nth 1 base-corners) (interp-coords (nth 1 top-corners) (nth 0 top-corners) 0.5))
         (draw-line (nth 2 base-corners) (interp-coords (nth 2 top-corners) (nth 1 top-corners) 0.5))))
      ((equal option "X")
       (progn
         ;; Add lines to create the K bracing pattern
         (draw-line (nth 0 base-corners) (nth 2 top-corners))
         (draw-line (nth 1 base-corners) (nth 0 top-corners))
         (draw-line (nth 2 base-corners) (nth 1 top-corners))
         ;; Add lines to complete the K bracing pattern
         (draw-line (nth 0 base-corners) (nth 1 top-corners))
         (draw-line (nth 1 base-corners) (nth 2 top-corners))
         (draw-line (nth 2 base-corners) (nth 0 top-corners))))
      ((equal option "Z")
       (progn
         ;; Add lines to create the Z bracing pattern
         (draw-line (nth 0 base-corners) (nth 1 top-corners))
         (draw-line (nth 1 base-corners) (nth 2 top-corners))
         (draw-line (nth 2 base-corners) (nth 0 top-corners))))))

  ;; Initialize dimensions for the first segment
  (setq current-base-width base-width)
  (setq current-top-width (+ base-width (/ (- top-width base-width) (float num-segments))))
  (setq current-height 0)

  ;; Draw the segments based on shape/ geometry type
  (repeat num-segments
    (setq base-corners (if (equal shape "4")
                           (list
                             (list (- (/ current-base-width 2.0)) (- (/ current-base-width 2.0)) current-height)
                             (list (- (/ current-base-width 2.0)) (/ current-base-width 2.0) current-height)
                             (list (/ current-base-width 2.0) (/ current-base-width 2.0) current-height)
                             (list (/ current-base-width 2.0) (- (/ current-base-width 2.0)) current-height))
                           (list
                             (list (- (/ current-base-width 2.0)) (/ (* (sqrt 3) current-base-width) 6.0) current-height)
                             (list (/ current-base-width 2.0) (/ (* (sqrt 3) current-base-width) 6.0) current-height)
                             (list 0.0 (- (/ (* (sqrt 3) current-base-width) 3.0)) current-height)))
          top-corners (if (equal shape "4")
                          (list
                            (list (- (/ current-top-width 2.0)) (- (/ current-top-width 2.0)) (+ current-height segment-height))
                            (list (- (/ current-top-width 2.0)) (/ current-top-width 2.0) (+ current-height segment-height))
                            (list (/ current-top-width 2.0) (/ current-top-width 2.0) (+ current-height segment-height))
                            (list (/ current-top-width 2.0) (- (/ current-top-width 2.0)) (+ current-height segment-height)))
                          (list
                            (list (- (/ current-top-width 2.0)) (/ (* (sqrt 3) current-top-width) 6.0) (+ current-height segment-height))
                            (list (/ current-top-width 2.0) (/ (* (sqrt 3) current-top-width) 6.0) (+ current-height segment-height))
                            (list 0.0 (- (/ (* (sqrt 3) current-top-width) 3.0)) (+ current-height segment-height)))))

    ;; Draw the tower segment
    (if (equal shape "4")
      (draw-segment-4 base-corners top-corners)
      (draw-segment-3 base-corners top-corners))

    ;; Draw the bracings
    (if (equal shape "4")
      (draw-additional-lines-4 base-corners top-corners option)
      (draw-additional-lines-3 base-corners top-corners option))

    ;; Update dimensions for the next segment
    (setq current-base-width current-top-width)
    (setq current-top-width (+ current-base-width (/ (- top-width base-width) (float num-segments))))
    (setq current-height (+ current-height segment-height)))

  ;; Restore original settings
  (if (numberp original-ortho) (setvar 'orthomode original-ortho))
  (if (numberp original-osmode) (setvar 'osmode original-osmode))
  (if original-cecolor (setvar 'CECOLOR original-cecolor))

  ;; Clean up and exit
  (setq *error* nil)
  ;; Main function with error trapping
  (setq *error* error-handler)
  (setvar 'CECOLOR "BYLAYER") ; Ensure CECOLOR is set to a valid value
  (princ)
  (vla-regen (vla-get-activeDocument (vlax-get-acad-object)) acAllViewports); Regenerate active sheet
);end defun

;start the routine
(c:TOWER)

 

Link to comment
Share on other sites

Some preliminary thoughts. I have zero experience with towers, so feel free to dismiss everything.

 

1) You could add a vertical spacing parameter, which defaults to zero. In the draw-line subroutine, add the spacing parameter to the Z coordinate; if it's zero, no harm done. Wait, the vertical member isn't perpendicular to the ground? Use the interpolation function to locate that point.

 

2) If you need the vertical members for each segment to draw the next one up, could you put them on a separate layer? Then, when you're done, draw one line up the whole structure and erase the individual members. Or draw the one line first.

 

3) It would help if there was some logic behind the type of pattern, such as "K bracing in base, X in transition" or "Z bracing for width > 5000, X otherwise".

 

Something else to consider: once you draw one side of the tower, can you mirror it or copy it correctly to make the other sides? That might save some effort and complexity.

Link to comment
Share on other sites

Posted (edited)
12 minutes ago, CyberAngel said:

Some preliminary thoughts. I have zero experience with towers, so feel free to dismiss everything.

 

1) You could add a vertical spacing parameter, which defaults to zero. In the draw-line subroutine, add the spacing parameter to the Z coordinate; if it's zero, no harm done. Wait, the vertical member isn't perpendicular to the ground? Use the interpolation function to locate that point.

 

2) If you need the vertical members for each segment to draw the next one up, could you put them on a separate layer? Then, when you're done, draw one line up the whole structure and erase the individual members. Or draw the one line first.

 

3) It would help if there was some logic behind the type of pattern, such as "K bracing in base, X in transition" or "Z bracing for width > 5000, X otherwise".

 

Something else to consider: once you draw one side of the tower, can you mirror it or copy it correctly to make the other sides? That might save some effort and complexity.

Thanks for the reply, on your point 1) I tried all the itterations I could think of, but started losing the tapered line accuracy as it was no longer aligning with the rest of the "Main Leg". On your point 2) perhaps that is the right method, I honestly never though of that approach. So, basically, I would continue with the segments as is then draw a line to represent "Assembly length of the leg", I love that idea since I am stuck in modifying the draw-line function. On your point 3) The logic lies with the Engineer in charge and the calculations to base the bracing pattern or the existing tower on-site. So the logic is the Engineering part of the tower not a pre-defined set of logic. and your last point: I am drawing a 3D stick, so functions are degined to create each face equally the same type, shape and figure.

Thank you greatly for your feedback and thoughts @CyberAngel

Edited by Sambuddy
Link to comment
Share on other sites

A question (cond ((getint (strcat "\nEnter Number of Segments " would this not be based on some max distance ? Even if have rules re tower section height max spacing.

 

Please show 3 sided & 4 sided, K X Z shapes, dwg or image.

 

Is the sides,1 single line ? Did not wade through code to work that out. 

 

Not sure why you need to make lists of points rather than just calc as you go. 

 

 

 

 

Link to comment
Share on other sites

13 minutes ago, BIGAL said:

A question (cond ((getint (strcat "\nEnter Number of Segments " would this not be based on some max distance ? Even if have rules re tower section height max spacing.

 

Please show 3 sided & 4 sided, K X Z shapes, dwg or image.

 

Is the sides,1 single line ? Did not wade through code to work that out. 

 

Not sure why you need to make lists of points rather than just calc as you go. 

 

 

 

 

- Yes, total tower height/ number of segments = each segment height (base on vertical distance, not tapered distance). in fact, all the unser input distances are based on a vertical distance and not the actual distance of the member. Since the original mesurements are given by the user based on a 2D elevation or plan view. In this way, I can then measure the real distance of any bracing/ tapered line.

- Please see attached DWG + the snapshots. I have included all the possible 3/4 sided tower and all the possible bracing types on the dwg file.

- That is the ONLY way I knew, that is through list and interpolation. I have a long way to get to your level of thinking and data processing @BIGAL.

Thank you @BIGAL for taking the time to take a look at my problem.

image.thumb.png.6167940304131e0edb89cb3acaaed6a6.png

Tower Example.dwg

Link to comment
Share on other sites

Understand more now your drafting in 3D yes a complicated task. Will have a think about it and look at code again.

 

One maybe easier way is draw each side in 2d and user Rotate3d. For the 3 sided that is pretty easy as just use copy 3 times. The 4 side again lay down in a left right up down pattern and stand up as 2 sides will not have the long edges.

Link to comment
Share on other sites

@Sambuddy In response to your first question, the following code with determine the location of a point on a diagonal at a given vertical distance (i.e., in the z world direction) from the lower point of the diagonal going from point A to point B.

image.png.993472abe1e8b76552583e2dffdb0feb.png 

(defun c:test (/ A B v uAB d p osm)
  (setq	A   (getpoint "\nSpecify lower point on diagonal: ")
	B   (getpoint "\nSpecify upper point on diagonal: ")
	v   (getreal "\nSpecify vertcal displacement: ")
	uAB (unitvec (mapcar '- B A))
	d   (/ v (caddr uAB))
	p   (mapcar '+ A (mapcar '* uAB (list d d d)))
  )
  (setq osm (getvar 'osmode))
  (setvar 'osmode 0)
  (command "_point" p "")
  (setvar 'osmode osm)
  (princ)

)
					; Unit vector of v
(defun unitvec (v / x)
  (setq	x (distance '(0 0 0) v)
	x (mapcar '/ v (list x x x))
  )
)

 

Edited by lrm
Link to comment
Share on other sites

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...