PDA

View Full Version : Node extraction

Hari Prashanth
13th Feb 2011, 08:20 am
Hi all...
Im using AUTOlisp to extract the coordinates out of a 2D figure to an excel file.
Ive attached a figure for reference too.

I've to follow some conditions regarding the figures...
1. The figure must be in posotive quardrant only.
2. The coordinate extraction must always start from the origin .ie (0,0).
3. Proceed along the line
4. Proceed along the pentagon
5. And finish at the same point where the line meets the figure or one node before that.

Here s procedure i m following...
1.Ill draw the figure.
2.Divide it into many nodes with 'divide' command.

Ive attached the LISP coding and the sample figure.
Any suggestions would be helpful. Pls help.

Tharwat
13th Feb 2011, 09:35 am
Codes removed due to ignorance !!

Tharwat

Smirnoff
13th Feb 2011, 12:23 pm
It looks as student home work. Are you sure that your professor does not participate in this forum? 8)

Ok. some help for you. But not full of course. You don't need to use DIVIDE command but extract vertexes (nodes) of line and polyline (pentagon). There is sample code:

(defun c:test2(/ cLn cPl lLst pLst)
(if
(and
(setq cLn(entsel "\nPick line > "))
(setq cPl(entsel "\nPick pentagon > "))
); and
(progn
(setq cLn(entget(car cLn)) ; get DXF-codes of line
cPl(entget(car cPl)) ; get DXF-codes of polyline
lLst(list ; extract list of ((start pt)(end pt)) for line
(cdr(assoc 10 cLn))
(cdr(assoc 11 cLn))
); end list
pLst(mapcar 'cdr ; extract list ((vertex1)(vertex2)...) for polyline
(vl-remove-if-not
'(lambda(i)(= 10(car i)))cPl))
); end pLst
); end progn
); end if
(list lLst pLst) ; returns ((list 1)(list 2))
); end of c:test2

Now you should to think, how to sort that coordinates to write it to text file in right order.

Hari Prashanth
15th Feb 2011, 05:07 am
Sir Smirnoff,
Your code was very helpful. Sorry i m new to autoCAD and autoLISP. This ain't my field of study too. This is a part of my project 'developin a CNC machine'. Ive understood most of the parts from comments which u ve incuded. Thank u for that. When i try to save it in a TXT file or CSV file it appears empty. Ive enclosed the code below. Pls help me out with this.

(defun c:test2(/ cLn cPl lLst pLst fn f )
(if
(and
(setq cLn(entsel "\nPick line > "))
(setq cPl(entsel "\nPick pentagon > "))
); and
(progn
(setq cLn(entget(car cLn)) ; get DXF-codes of line
cPl(entget(car cPl)) ; get DXF-codes of polyline
lLst(list ; extract list of ((start pt)(end pt)) for line
(cdr(assoc 10 cLn))
(cdr(assoc 11 cLn))
); end list
pLst(mapcar 'cdr ; extract list ((vertex1)(vertex2)...) for polyline
(vl-remove-if-not
'(lambda(i)(= 10(car i)))cPl))
); end pLst
); end progn
); end if
(list lLst pLst) ; returns ((list 1)(list 2))

(if (not (setq fn (getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn (alert "No file selected!") (quit))
)

(setq f (open fn "w"))
(princ (strcat (rtos (car llst)) "," (rtos (cadr llst))"\n") f)
(close f)

(setq f (open fn "w"))
(princ (strcat (rtos (car plst)) "," (rtos (cadr plst))"\n") f)
(close f)

(alert (strcat "Finish export points to file: " fn))
); end of c:test2

pBe
15th Feb 2011, 06:16 am
Sir Smirnoff,
Your code was very helpful. Sorry i m new to autoCAD and autoLISP. This ain't my field of study too. This is a part of my project 'developin a CNC machine'. Ive understood most of the parts from comments which u ve incuded. Thank u for that. When i try to save it in a TXT file or CSV file it appears empty. Ive enclosed the code below. Pls help me out with this.

not sure how you wanted your output to look,

(defun
c:test2 (/ cLn cPl lLst pLst fn f)
(if (and
(setq cLn (entsel "\nPick line > "))
(setq cPl (entsel "\nPick pentagon > "))) ; and
(progn
(setq
cLn (entget (car cLn)) ; get DXF-codes of line
cPl (entget (car cPl)) ; get DXF-codes of polyline
lLst (list ; extract list of ((start pt)(end pt)) for line
(cdr (assoc 10 cLn))
(cdr (assoc 11 cLn))) ; end list
pLst (mapcar
'cdr ; extract list ((vertex1)(vertex2)...) for polyline
(vl-remove-if-not '(lambda (i) (= 10 (car i))) cPl)))
; end pLst
) ; end progn
) ; end if
(list lLst pLst) ; returns ((list 1)(list 2))
(if (not
(setq
fn
(getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn (alert "No file selected!") (quit)))
(setq f (open fn "a"))
(write-line
(strcat
(vl-princ-to-string (car llst))
","
f)
(write-line
(strcat
(vl-princ-to-string (car plst))
","
f)
(close f)
(alert (strcat "Finish export points to file: " fn)))

the result will look like this
two columns
Column A
(-122.807 179.928 0.0)
(-4.48415 271.639 0.0)
(118.262 191.53)
(167.471 248.987)
Column B
(-122.807 179.928 0.0)
(-4.48415 271.639 0.0)
(118.262 191.53)
(167.471 248.987)

I change this
(open fn "w")
to this
(open fn "a"))

w- Open for writing. If filename does not exist, a new file is created and opened. If filename already exists,
its existing data is overwritten. Data passed to an open file is not actually written until the file is closed with the close function.

while

a- Open for appending. If filename does not exist, a new file is created and opened. If filename already exists,
it is opened and the pointer is positioned at the end of the existing data, so new data you write to the file is appended to the existing data.

Hope this helps :)

Hari Prashanth
15th Feb 2011, 09:13 am
Sir pBE,
Ive understood about write and append modes. But the code didn't print as u told. It jus prints the two end points of the line and only one vertex of the pentagon. Pls help.

pBe
15th Feb 2011, 01:02 pm
Sir pBE,
Ive understood about write and append modes. But the code didn't print as u told. It jus prints the two end points of the line and only one vertex of the pentagon. Pls help.

Ooops :o

you're right.
The thing that gets me is
for the points of your polygon you still want it as two columns, anyway..

(defun
c:test2 (/ cLn cPl lLst pLst fn f)
(if (and
(setq cLn (entsel "\nPick line > "))
(setq cPl (entsel "\nPick pentagon > "))) ; and
(progn
(setq
cLn (entget (car cLn)) ; get DXF-codes of line
cPl (entget (car cPl)) ; get DXF-codes of polyline
lLst (list ; extract list of ((start pt)(end pt)) for line
(cdr (assoc 10 cLn))
(cdr (assoc 11 cLn))) ; end list
pLst (mapcar
'cdr ; extract list ((vertex1)(vertex2)...) for polyline
(vl-remove-if-not '(lambda (i) (= 10 (car i))) cPl)))
; end pLst
) ; end progn
) ; end if
(list lLst pLst) ; returns ((list 1)(list 2))
(if (not
(setq
fn
(getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn (alert "No file selected!") (quit)))
(setq f (open fn "a"))
(write-line
(strcat
(vl-princ-to-string (car llst))
","
f)
(repeat (/ (length plst) 2)
(write-line
(strcat
(vl-princ-to-string (car plst))
","
f)
(setq plst (cdr (member (cadr plst) plst )))
)

(close f)
(alert (strcat "Finish export points to file: " fn)))

Result
(17.735 225.294 0.0) (80.5574 286.498 0.0)<-- for line (assoc 10/11)
(186.963 272.374) (139.364 271.642)<-- for polygon (6 points)(six sides)
(116.199 230.055) (140.631 189.199)
(188.23 189.931) (211.396 231.517)

but if you want single column for your polygon

(defun
c:test2 (/ cLn cPl lLst pLst fn f)
(if (and
(setq cLn (entsel "\nPick line > "))
(setq cPl (entsel "\nPick pentagon > "))) ; and
(progn
(setq
cLn (entget (car cLn)) ; get DXF-codes of line
cPl (entget (car cPl)) ; get DXF-codes of polyline
lLst (list ; extract list of ((start pt)(end pt)) for line
(cdr (assoc 10 cLn))
(cdr (assoc 11 cLn))) ; end list
pLst (mapcar
'cdr ; extract list ((vertex1)(vertex2)...) for polyline
(vl-remove-if-not '(lambda (i) (= 10 (car i))) cPl)))
; end pLst
) ; end progn
) ; end if
(list lLst pLst) ; returns ((list 1)(list 2))
(if (not
(setq
fn
(getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn (alert "No file selected!") (quit)))
(setq f (open fn "a"))
(write-line
(strcat
(vl-princ-to-string (car llst))
","
f)
(repeat (length plst)
(write-line
(vl-princ-to-string (car plst))
f)
(setq plst (cdr plst))
)

(close f)
(alert (strcat "Finish export points to file: " fn)))

Result
(17.735 225.294 0.0) (80.5574 286.498 0.0)<-- for line (assoc 10/11)
(186.963 272.374) <-- for polygon (6 points)(six sides)
(139.364 271.642)
(116.199 230.055)
(140.631 189.199)
(188.23 189.931)
(211.396 231.517)

Hari Prashanth
15th Feb 2011, 01:52 pm
Thanks a lot Sir pBe, your code definately helped.
This is ok when i extract points from regular shapes. What if i try to extract coor from an arc or an eclipse segment or an irregular arc.... So i gotta divide the arc into nodes and extract at regular intervals. That is what i ve been asking at the fisrt place. How could i do so? Thanks in advance.

pBe
16th Feb 2011, 12:08 pm
Thanks a lot Sir pBe, your code definately helped.
This is ok when i extract points from regular shapes. What if i try to extract coor from an arc or an eclipse segment or an irregular arc.... So i gotta divide the arc into nodes and extract at regular intervals. That is what i ve been asking at the fisrt place. How could i do so? Thanks in advance.

you dont really need to divide the object with nodes to get the points within an arc.
look at this sample, given a constant interval say at every 10

(defun test (val / objts objt_length strt_pt pts valA)
(setq objts (vlax-ename->vla-object (car (entsel))))
(setq objt_length (vlax-curve-getDistAtParam objts
(vlax-curve-getEndParam objts)))
(setq strt_pt (vlax-curve-getStartPoint objts))
(setq pts (list strt_pt) valA val)
(repeat (fix (/ objt_length val))
(setq pts (cons (vlax-curve-getPointAtDist objts val) pts)
val (+ val valA))
)
(setq pts (reverse (cons (vlax-curve-getendpoint objts) pts)))
(foreach pt pts
(print pt)
)
(princ)
)

USAGE:
command: (test 10)<---- where 10 is your interval value
command: Select object:

Result:
(242.391 222.255 0.0)<---startpoint
(233.314 226.444 0.0)<--- pts at 10.00 interval
(223.933 229.9 0.0)
(214.308 232.602 0.0)
(204.498 234.532 0.0)
(194.567 235.678 0.0)
(184.576 236.033 0.0)
(174.588 235.595 0.0)
(164.666 234.366 0.0)
(154.874 232.355 0.0)<-- pts at 10.00 interval
(148.552 230.617 0.0)<-- remainder to endpoint

Hope this helps
And... stop calling me sir :)

Hari Prashanth
16th Feb 2011, 05:47 pm
Well thanks a lot. That solves my querry. Sorry for what i m gonna ask hereafter. Can i get the code for printing those values in an excel or CSV file. When i tried it prints only two values. And... Instead of extracting it as a point itself in this frm ( , ) can it extract 'x' values in one column and 'y' in another column.

This is the code i ve been using...
(defun tst5 (val / objts objt_length strt_pt pts valA fn f)
(setq objts (vlax-ename->vla-object (car (entsel))))
(setq objt_length (vlax-curve-getDistAtParam objts
(vlax-curve-getEndParam objts)))
(setq strt_pt (vlax-curve-getStartPoint objts))
(setq pts (list strt_pt) valA val)
(repeat (fix (/ objt_length val))
(setq pts (cons (vlax-curve-getPointAtDist objts val) pts)
val (+ val valA))
)
(setq pts (reverse (cons (vlax-curve-getendpoint objts) pts)))

(setq fn(getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn (alert "No file selected!") (quit)))

(foreach pt pts

(if (not

(setq f (open fn "a"))
(write-line
(strcat
(vl-princ-to-string (car pt))
","
f)

(close f)
(alert (strcat "Finish export points to file: " fn)))

pBe
17th Feb 2011, 05:57 am
Well thanks a lot. That solves my querry. Sorry for what i m gonna ask hereafter. Can i get the code for printing those values in an excel or CSV file. When i tried it prints only two values. And... Instead of extracting it as a point itself in this frm ( , ) can it extract 'x' values in one column and 'y' in another column.

Try this:

(defun tst5 (val / objts objt_length strt_pt pts valA fn f)
(cond ((and
(setq objts (car (entsel)))
(setq
objt_length
(vlax-curve-getDistAtParam
objts
(vlax-curve-getEndParam (vlax-ename->vla-object objts))))
(setq strt_pt (vlax-curve-getStartPoint objts))
(setq
pts (list strt_pt)
valA val)
(repeat (fix (/ objt_length val))
(setq
pts (cons (vlax-curve-getPointAtDist objts val) pts)
val (+ val valA)))
(setq pts (reverse (cons (vlax-curve-getendpoint objts) pts)))
(if (not
(setq
fn
(getfiled "Export to file" (getvar "dwgprefix") "csv" 1)))
(progn
(setq f (open fn "a"))
(foreach
pt pts
(write-line
(strcat (rtos (car pt)) "," (rtos (cadr pt) 2 4))
f))
(close f)
(alert (strcat "Finish export points to file: " fn))))
)
)
)
(princ)
)

There's a lot of misplaced parenthesis and functions on the code you posted:

This time you dont need to use vl-princ-to-string to write the values, since you're not writing a list.
[thats the reason we did that on the first place]

by doing this
(write-line
(strcat (vl-princ-to-string (car pt)) "," (vl-princ-to-string (cadr pt))) f)
the result will be
Column A Column B
2.32328e+007 1.45359e+008<-- literal translation
while this
(write-line (strcat (rtos (car pt)) "," (rtos (cadr pt) 2 4)) f)
will give you
Column A Column B
23232768.8310 145358905.9378

I thnk what you should do is, on your routine make a condition to check for entity type, pline/line/arc/ellipse and assign a set of variables for every condition
that way you only need to write one code

Hari Prashanth
17th Feb 2011, 06:18 pm
Whoopy thanks a lot. That was very kind of u... U ve guided me inch by inch even though i didn't know anythin regardin AutoLISP. That meant a lot to me. I don't know how to repay u. I think i am a bit versed in Programming languages such as C,CPP and java to some extent... If there is something regarding programming i could lend a bit of an assistance. Thanks again pBe.