Lisp Routine for Creating a Chamfer Line of Fixed Length

Lisp Routine for Creating a Chamfer Line of Fixed Length

Yasir.Aman
Advocate Advocate
3,242 Views
36 Replies
Message 1 of 37

Lisp Routine for Creating a Chamfer Line of Fixed Length

Yasir.Aman
Advocate
Advocate

I searched the forums but couldn't find an existing solution.

I'm looking for a Lisp routine that creates a chamfer line of a fixed length, provided by the user. The routine should calculate the distances for Distance 1 and Distance 2 (which are usually user-defined in AutoCAD's built-in chamfer command).

In my case, both distances for Line 1 and Line 2 will be equal. The angle between Line 1 and Line 2 can be anything greater than 0 and less than 180 degrees.

Please refer to the attached image for further clarification.

Thank you all!

 

For-Chamfer-Lisp.png

0 Likes
Accepted solutions (1)
3,243 Views
36 Replies
Replies (36)
Message 2 of 37

komondormrex
Mentor
Mentor

are the red ones always lines?

0 Likes
Message 3 of 37

Moshe-A
Mentor
Mentor

@Yasir.Aman hi,

 

check this:

 

(defun c:chbycord (/ askdist ; local function
		     chord edge)

 (defun askdist (msg def / ask)
  (initget (+ 2 4))
  (if (not (setq ask (getdist (strcat "\n" msg " <" (rtos def 2) ">: "))))
   (setq ask def)
   (setq def ask)
  ); if
 ); askdist


 (if (setvar "userr5" (setq chord (askdist "Specify cord length" (getvar "userr5"))))
  (progn
   (setq edge (sqrt (/ (expt chord 2) 2)))
   (initcommandversion 2)
   (command-s "._chamfer" "_Multiple" "_Method" "_Distance" "_Distance" edge edge)
  ); progn
 ); if
  
 (princ)
); c:chbycord

 

Message 4 of 37

Kent1Cooper
Consultant
Consultant
Accepted solution

@Yasir.Aman wrote:

... a Lisp routine that creates a chamfer line of a fixed length, provided by the user. .... The angle between Line 1 and Line 2 can be anything....


The CW command defined in ChamferWidth.lsp does that, and not just for a 45° Chamfer of things at a 90° angle as Message 3 is limited to.  Available >here<.

 

It does have the drawback that it works only with Lines.  Maybe I'll work on expanding the possibilities.

 

[And by the way, the word is "chord" with an "h" in it.]

Kent Cooper, AIA
Message 5 of 37

john.uhden
Mentor
Mentor

@Moshe-A ,

@Yasir.Aman wrote, "The angle between Line 1 and Line 2 can be anything greater than 0 and less than 180 degrees."

Your solution is well done but good for a 90°angle only.

Chord = C=2Rsin (D/2) ;; where R would be the radius and D is the delta angle

Edge = Tangent = T = Rtan (D/2)

You have to do the trigonometry to compute the edge from the chord knowing that...

tan = sin/cos

sin^2 + cos^2 = 1 (not needed, I think)

John F. Uhden

Message 6 of 37

Yasir.Aman
Advocate
Advocate

Mostly lines, sometimes polylines, even (sometimes it may be) a single polyline with a corner that needs to be chamfered. For me a code that works only with lines is good enough as exploding a couple of polylines is not a big deal.

That being said, if the code is able to deal with the polylines, the extra convenience is always welcome. 😊

Thank you.

0 Likes
Message 7 of 37

Yasir.Aman
Advocate
Advocate
Thank you for your response. This works perfectly, but only for 90-degree corners. The resulting chord is not of correct length if the angle between lines is other that 90-degrees.
0 Likes
Message 8 of 37

Yasir.Aman
Advocate
Advocate

Bravo Mr. @Kent1Cooper. It works flawlessly with lines. For now, this is perfect for my needs. However, if you happen to improve this for polylines, do share your work please. I am sure it will help a lot of people.

Thank you very much. 😍

0 Likes
Message 9 of 37

komondormrex
Mentor
Mentor

all-linear segments plines or mixed? 

Message 10 of 37

Kent1Cooper
Consultant
Consultant

@komondormrex wrote:

all-linear segments plines or mixed? 


An essential question!  I did some experimenting, wondering whether CHAMFER would even work at all with Polyline arc segments.  It does, but it changes them!  Here, the red ones are the originals, and the yellow the result of CHAMFERing:

Kent1Cooper_0-1722768033616.png

I suspect it's keeping the bulge factor of each arc what it was, and the end away from the CHAMFERing where it was.

 

So if Polyline arc segments are involved, it should not be done by calculating CHAMFER Distances and then applying the command, but by calculating somehow where the chord Line should go, drawing that and TRIMming the Polyline to it.  The big problem would be figuring where the Line should go -- there are infinite solutions:

Kent1Cooper_1-1722768782945.png

Presumably one would want the one that takes the same amount of length off each arc segment.  I think that would not be just calculable, but would need a trial and a test, a refinement and another trial, etc., until a solution is within some tolerance.

Kent Cooper, AIA
Message 11 of 37

Yasir.Aman
Advocate
Advocate

In my case, all linear segments.

0 Likes
Message 12 of 37

Yasir.Aman
Advocate
Advocate

I am pretty glad to see my "linear" question turn into a fun thought provoking exercise. 😊

 

So if Polyline arc segments are involved, it should not be done by calculating CHAMFER Distances and then applying the command, but by calculating somehow where the chord Line should go, drawing that and TRIMming the Polyline to it.  The big problem would be figuring where the Line should go -- there are infinite solutions:

Kent1Cooper_1-1722768782945.png

Presumably one would want the one that takes the same amount of length off each arc segment.  I think that would not be just calculable, but would need a trial and a test, a refinement and another trial, etc., until a solution is within some tolerance.


I'd love to see a solution like that, but (in my humble opinion) I don't think users face this situation every day. Of course, I could be wrong. While I mostly deal with civil infrastructure, people in mechanical fields might find such a tool very useful. Who knows?

0 Likes
Message 13 of 37

john.uhden
Mentor
Mentor

@Kent1Cooper ,

This would be a simple way (so long as the legs are treated as straight chords, not arc lengths)...

johnuhden_0-1722780121558.png

It's as easy as 1, 2, 3 ... the colors, get it?

Oh, wait a minute there, Uhden.  Yes, we start with the red, but then the length of the green comes 2nd.

It IS looking more like trial and error. 😵

John F. Uhden

Message 14 of 37

daniel_cadext
Advisor
Advisor

"Presumably one would want the one that takes the same amount of length off each arc segment.  I think that would not be just calculable"

 

You can roll up to it with pretty good accuracy. I'm sure someone good at math could do it better than me. here's a proof of concept

 

 

 

from pyrx_imp import Ap, Db, Ed, Ge, Gi, Gs, Rx
import traceback

def PyRxCmd_doit():
    try:
        db = Db.curDb()
        
        #dist
        es , dist = Ed.Editor.getDist("\nDistance: ")
        if es != Ed.PromptStatus.eOk:
            raise RuntimeError("nDistance Error {}: ".format(es)) 

        #entsel
        es, id, epnt = Ed.Editor.entSel("\nPick a Polyline: ", Db.Polyline.desc())
        if es != Ed.PromptStatus.eOk:
            raise RuntimeError("Entsel Error! {}: ".format(es)) 

        pl = Db.Polyline(id,Db.OpenMode.kForWrite)
        
        #get param at pick
        epnt = pl.getClosestPointTo(epnt)
        nextParam = float(int(pl.getParamAtPoint(epnt))) +1
        distAtVertex = pl.getDistAtParam(nextParam)
    
        #compute split points
        d = 0.0
        pnt1 = Ge.Point3d()
        pnt2 = Ge.Point3d()
        for i in range(1,15):
            tol = 10 ** -i
            while(pnt1.distanceTo(pnt2) < dist - (tol*2)):
                d += tol
                pnt1 = pl.getPointAtDist(distAtVertex-d)
                pnt2 = pl.getPointAtDist(distAtVertex+d)
           
        #check     
        print(pnt1.distanceTo(pnt2))
             
        #split the curves    
        newplines = []
        plines = pl.getSplitCurves([pnt1])
        newplines.append(plines[0])
        pline = Db.Polyline([pnt1,pnt2])
        newplines.append(pline)
        plines = pl.getSplitCurves([pnt2])
        newplines.append(plines[len(plines)-1])
        
        #color 
        for item in newplines:
            item.setColorIndex(1)
            
        #join the new segment
        pe = Db.JoinEntityPE(newplines[0].queryX(Db.JoinEntityPE.desc()))
        pe.joinEntities(newplines[0], newplines[1:])
        db.addToCurrentspace(newplines[0])
        
        #pl.erase()
    except Exception as err:
        traceback.print_exception(err)

 

 

 

cap.png

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 15 of 37

Yasir.Aman
Advocate
Advocate

@daniel_cadext Thank you for your valuable input.

The screen capture you shared looks very promising. Unfortunately, I'm not very familiar with how to use Python code in AutoCAD. Could you please guide me on where to start? A getting started guide or something similar would be greatly appreciated.

0 Likes
Message 16 of 37

Kent1Cooper
Consultant
Consultant

I'm not familiar with Python, either, but line 31 and following look like they are doing just what I suspected would be needed -- it's not a direct calculation, but a matter of trying a value, testing the distance between resulting points, and adjusting the value to get closer to the desired distance, until the result falls within the required tolerance.  The same could be done in AutoLisp terms.

Kent Cooper, AIA
Message 17 of 37

daniel_cadext
Advisor
Advisor

“The same could be done in AutoLisp terms.”

 

Right! I think default tolerance for AutoCAD’s internal equalPoint is 1e-10

https://help.autodesk.com/view/OARX/2023/ENU/?guid=OARX-RefGuide-AcGeTol

 

Probably best to get close to that just in case 'pedit' or 'join' need that accuracy

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 18 of 37

daniel_cadext
Advisor
Advisor

Hi, the link is in the my description, source, with some instructions on how to install and a bunch of samples.

I have not written a ‘started guide’ yet, still kind of a hacker thing

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 19 of 37

komondormrex
Mentor
Mentor

@daniel_cadext 

this is holy everything but the autolisp, visual lisp and general customization imo.

0 Likes
Message 20 of 37

Kent1Cooper
Consultant
Consultant

... and of course, there are limitless possible configurations with multiple solutions of the same Chamfer-piece length at the same distance down both sides from a vertex.  Just a couple of examples:

Kent1Cooper_0-1722865211052.png

in which cases I assume the desired result would be the one closest to the vertex.

 

But a potential difficulty arises.  Let's say the first-shot attempt in the left image, depending on how it comes up with a first try, lands just to the right of the right-hand yellow line.  The potential Line there will be too short, which in most circumstances would suggest that the next try should be farther from the vertex.  But that will only make the result shorter, and then it will try even farther away, for a result even shorter for a while until the spacing gets to widening again, and in that particular Polyline going all the way to the ends won't reach the desired Line length.  It probably wouldn't be able to know [or it could at least be a coding challenge to get it to realize] that it should try going the other way from the first attempt.

 

I assume there's no way to account for all possible configurations in a fool-proof way, so there will probably always be situations that a routine can't handle.

Kent Cooper, AIA