3d Polyline slope routine needed

3d Polyline slope routine needed

Anonymous
Not applicable
7,789 Views
43 Replies
Message 1 of 44

3d Polyline slope routine needed

Anonymous
Not applicable

Im in need of a command or routine that will take a flat polyline and slope it at a certain degree or run. 

For example, I drew a polyline from point A to B.  It includes arcs and straights and isnt closed.  I want to set point A at some elevation like 12'-0",  and then have a routine that will slope the polyline consistently from A to B at 1/4" every 12" or even 5/16" every 12".  Is there something like that anywhere or can someone help me out please?  Id be really grateful.

 

 

0 Likes
Accepted solutions (3)
7,790 Views
43 Replies
Replies (43)
Message 21 of 44

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Im getting "a malformed list on input" when I load this.  Something missing?


No -- something extra.  Remove the red one from this:

 

(defun c:slopepl ( /  (D1 D2 ....

 

[I didn't load and test it, so that may not be the only issue.]

Kent Cooper, AIA
0 Likes
Message 22 of 44

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

..... A bit tricky working feet and inches.

....
(defun cvfrac (str / pos dec1 dec2)
(setq pos (vl-string-search "/" str))
(if (not pos)
(princ (atof str))
(progn
(setq dec1 (atof (substr str 1 pos)))
(setq dec2 (atof (substr str (+ pos 2))))
(princ (/ dec1 dec2))
)
)
)
....
(setq slp (cvfrac (getstring "\nEnter slope as fraction of inch per foot ")))
....

It doesn't need to be tricky.  Just for your information, if your Units are Architectural, you can use the (getdist) function [instead of your (getstring)] and enter a value in fractional units  [with or without the inches mark at the end], and it will "interpret" it correctly and directly as a decimal number:

 

Command: (getdist)
{type in} 1/4"
{returns} 0.25

 

So you can eliminate that (cvfrac) function entirely.

 

Similarly, feet-inches-fractions  can be entered:

Command: (getdist)
{type in} 6'4-3/8
{returns} 76.375

Kent Cooper, AIA
0 Likes
Message 23 of 44

devitg
Advisor
Advisor

Hi Elvis. Did you try my lisp??

0 Likes
Message 24 of 44

Kent1Cooper
Consultant
Consultant
Accepted solution

If a 3DPolyline with short [or however long you want] line segments is acceptable, here's my take on it:

(defun C:S3DP ; = Slope conversion to 3DPolyline
  (/ osm esel ent elen bkw dp dz z pos)
  (setq
    osm (getvar 'osmode)
    esel (entsel "\nSelect path object near end for high end of result: ")
    bkw ; = backwards [high at downstream end]
      (> ; picked closer to end than to start [T or nil]
        (vlax-curve-getDistAtPoint (setq ent (car esel)) (osnap (cadr esel) "_nea"))
        (/ (setq elen (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))) 2)
      ); >
    dp (getdist "\nSpacing along original path per segment: "); delta along path
    dz (* (/ (getdist "\nDownward Slope per Foot: ") 12) dp); delta in Z direction
    z (getdist "\nStarting (high end) elevation: ")
    pos (if bkw elen 0); position [as length along path]
  ); setq
  (setvar 'osmode 0)
  (command "_.3dpoly" ".XY" (vlax-curve-getPointAtDist ent pos) z); start 3DPolyline
  (while (if bkw (>= (setq pos (- pos dp)) 0) (<= (setq pos (+ pos dp)) elen))
    (command ".XY" (vlax-curve-getPointAtDist ent pos) (setq z (- z dz)))
  ); while
  (setq pos ((if bkw + -) pos dp)); back to last within path length
  (if (not (equal pos (if bkw 0 elen) 1e-8)); didn't hit other end exactly
    (command; then -- last point [partial-dz drop]
      ".XY" (vlax-curve-getPointAtDist ent (if bkw 0 elen))
      (- z (* dz (/ (if bkw pos (- elen pos)) dp)))
    ); command
  ); if
  (command ""); end 3DPolyline
  (setvar 'osmode osm)
  (princ)
); defun

It works on any kind of finite object with linearity [Line, Arc, Circle, Polyline, Ellipse, Spline].  It takes advantage of point filtering [".XY"] so that it doesn't need to save a point location and extract X and Y coordinates from it, to apply the varying Z coordinate to.

 

It could easily be made to remember your choices for spacing and slope and starting elevation, and offer them as defaults on subsequent use, as well as the usual *error* handling, command-echo suppression, verification of selection of an appropriate object, etc.

Kent Cooper, AIA
0 Likes
Message 25 of 44

Anonymous
Not applicable

Yes I have.  Ive been using it all morning.  Thanks!

Im looking at the others also.  A couple more have inputs and also checks the pline direction to work either way.

0 Likes
Message 26 of 44

devitg
Advisor
Advisor

I made it as your need stated at the post . 

Glad  it help you. 

 

0 Likes
Message 27 of 44

john.uhden
Mentor
Mentor

Accuracy?

Even on a 10' radius, a chord length of 0.2500' produces an arc length of 0.2500'.  I tend to doubt that the slopes/grades required need be that precise.  Anyway, the additional 3Dpolyline vertices created ARE exactly on the arc's path.

John F. Uhden

0 Likes
Message 28 of 44

Anonymous
Not applicable

I like how it asks for the elevation and creates the 3d poly up there.  But sometimes it doesnt work.  Seems to be stalling out after I input the elevation.  Maybe Im not putting it in right according to the units.  Seems ok if I use like 20'3 but if I try 20'3.3125 for elevation it stalls.  Not sure how Im supposed to be inputting the elevation.  Id like to use Architectural units.

0 Likes
Message 29 of 44

Anonymous
Not applicable

Devitg, one other thing... I noticed on the 3dpoly starting point it misses the first segment.  If you look close where the line starts, youll see that it isnt the same start point.  Can you fix that?  Ive been stretching it but im sure its a quick fix?

0 Likes
Message 30 of 44

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....  Seems to be stalling out after I input the elevation.  Maybe Im not putting it in right according to the units.  Seems ok if I use like 20'3 but if I try 20'3.3125 for elevation it stalls.  ....



It doesn't do that for me, using exactly that input.  Are there any messages?

Kent Cooper, AIA
0 Likes
Message 31 of 44

Sea-Haven
Mentor
Mentor

Thanks Kent as I work metric its just so much easier, I realise the Elev input is not correct also and needs getdist.

0 Likes
Message 32 of 44

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

... I work metric ....


My routine should ask for the slope in a different way for metric use.  Would that typically be as a percentage?

Kent Cooper, AIA
0 Likes
Message 33 of 44

Sea-Haven
Mentor
Mentor

Depends say sewer uses 1 in for house connections, whereas say a pipe may be % or worse still either. Generally not a drop of say mm/m. I could be wrong as I don't do building services.

 

 

0 Likes
Message 34 of 44

CADaSchtroumpf
Advisor
Advisor

@Anonymous  a écrit :

Im looking at the others also.  A couple more have inputs and also checks the pline direction to work either way.


Hi,

My try:

(vl-load-com)
(defun encadre (num lst / inf sup)
  (foreach n lst
    (cond
      ((< n num)
       (setq inf
        (if inf
          (max n inf)
          n
        )
       )
      )
      ((> n num)
       (setq sup
        (if sup
          (min n sup)
          n
        )
       )
      )
    )
  )
  (list inf sup)
)
(defun add_vtx (add_pt ent_name / )
  (list
    (car (trans (vlax-curve-getpointatparam obj add_pt) 0 ent_name))
    (cadr (trans (vlax-curve-getpointatparam obj add_pt) 0 ent_name))
    0.0
  )
)
(defun new_z (p / rap)
  (setq rap (/ (getvar "viewsize") 50))
  (foreach n
    (mapcar
      '(lambda (x)
        (list
          ((eval (car x)) (car (trans p 0 1)) rap)
          ((eval (cadr x)) (cadr (trans p 0 1)) rap)
          (caddr (trans p 0 1))
        )
      )
    '((+ +) (+ -) (- +) (- -))
    )
    (grdraw (trans p 0 1) n 7)
  )
  (initget 3)
  (list (car p) (cadr p) (getreal "\nNew Z for this point?: "))
)
(defun c:PLto3DPL ( / js AcDoc Space interval alti n obj ename v_length ind l_pos nwl_pt l_2int l_base l_pt pr first next nw_pt)
  (princ "\nSelect polyline.")
  (setq js (ssget "_+.:E:S" '((0 . "*POLYLINE") (-4 . "<NOT") (-4 . "&") (70 . 112) (-4 . "NOT>"))))
  (cond
    (js
      (setq
        AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))
        Space
        (if (= 1 (getvar "CVPORT"))
          (vla-get-PaperSpace AcDoc)
          (vla-get-ModelSpace AcDoc)
        )
      )
      (initget 6)
      (setq interval (getdist "\nAdd a vertex every <1.0>?: ") alti 0.0)
      (if (not interval) (setq interval 1.0))
      (setq
        obj (ssname js 0)
        ename (vlax-ename->vla-object obj)
        v_length 0.0
        ind -1
        l_pos '()
        nwl_pt '()
        l_2int '()
        l_base '()
        pr 0
        l_pt (list (cons (setq ind 0) (list (new_z (vlax-curve-getStartPoint ename)) v_length)))
      )
      (redraw)
      (while (< v_length (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)))
        (if (and (vlax-curve-getParamAtDist ename (+ interval v_length)) (< (fix (vlax-curve-getParamAtDist ename (+ interval v_length))) (1+ pr)))
          (setq l_pt (cons (cons (setq ind (1+ ind)) (list (add_vtx (vlax-curve-getParamAtDist ename (setq v_length (+ interval v_length))) obj) v_length)) l_pt))
          (setq l_pt (cons (cons (setq ind (1+ ind)) (list (vlax-curve-getPointAtParam ename (setq pr (1+ pr))) (vlax-curve-getDistAtParam ename pr))) l_pt))
        )
        (if (not (vlax-curve-getParamAtDist ename (+ interval v_length))) (setq v_length (+ interval v_length)))
      )
      (setq
        l_pt (cons (cons (1+ ind) (list (new_z (vlax-curve-getEndPoint ename)) (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)))) l_pt)
        pr -1
      )
      (redraw)
      (foreach n (reverse l_pt)
        (if (eq (caddr (cadr n)) alti)
          (setq l_2int (cons n l_2int))
          (setq l_base (cons n l_base))
        )
      )
      (cond
        ((> (length l_base) 1)
          (foreach n (reverse l_pt)
            (cond
              ((eq (caddr (cadr n)) alti)
                (setq pos (encadre (car n) (mapcar 'car l_base)))
                (if (not (car pos))
                  (setq pos (list (cadr pos) (cadr (encadre (cadr pos) (mapcar 'car l_base)))))
                )
                (if (not (cadr pos))
                  (setq pos (list (car (encadre (car pos) (mapcar 'car l_base))) (car pos)))
                )
                (setq
                  first (assoc (car pos) l_base)
                  next (assoc (cadr pos) l_base)
                  nw_pt
                  (subst
                    (list
                      (car (cadr n))
                      (cadr (cadr n))
                      (+
                        (caddr (cadr first))
                        (*
                          (/ (- (caddr (cadr next)) (caddr (cadr first))) (- (caddr next) (caddr first)))
                          (- (caddr n) (caddr first))
                        )
                      )
                    )
                    (cadr n)
                    n
                  )
                )
              )
              (T (setq nw_pt n))
            )
            (setq nwl_pt (cons nw_pt nwl_pt))
          )
          (vla-put-Layer (vlax-invoke Space 'Add3dPoly (apply 'append (reverse (mapcar 'cadr nwl_pt)))) (vla-get-Layer ename))
          ;(vla-delete ename)
        )
      )
    )
  )
  (prin1)
)

 

0 Likes
Message 35 of 44

devitg
Advisor
Advisor
Accepted solution

Try it , please . 

Correction added 

 

0 Likes
Message 36 of 44

Anonymous
Not applicable

Oh this is handy when you dont know the slope.  It lets you set the ends and slopes it evenly between.  Very Cool.

0 Likes
Message 37 of 44

john.uhden
Mentor
Mentor
IMHO, it should be as a percentage. It is unitless and fathomable by all
disciplines.

John F. Uhden

0 Likes
Message 38 of 44

Anonymous
Not applicable

Just now needs to work for a pline drawn either way.  Left to right or right to left.  Would be even better if it incorporated some of the other peoples work like asking for the elevation at the start and then asks if it is sloping toward or away and lets u pick the line near the end. But its very nice even as it is.  So thank you for your hard work.

 

E

0 Likes
Message 39 of 44

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:
IMHO, it should be as a percentage. It is unitless and fathomable by all disciplines.

 

That makes sense, though if anyone who deals in these things has a different standard to suggest, chime in.  For anyone who wants to specify by slope percentage, instead of fall per foot, just replace the definition of the dz variable by changing this one line in the code in Message 24:

....
    dz (* (/ (getdist "\nDownward Slope percent: ") 100) dp); delta in Z direction
....

If you want 2% [essentially the same as 1/4" per foot], type in just 2 [not 0.02 -- it handles that conversion].

Kent Cooper, AIA
0 Likes
Message 40 of 44

john.uhden
Mentor
Mentor
Re: " Downward Slope percent: "

Why be restrictive?
3DEDIT accepts both positive and negative values and you can start a
transition at either end or even in the middle and go in either direction.
And if you walk through each vertex it tells you the grade back and grade
ahead.

John F. Uhden

0 Likes