PDA

View Full Version : Problem with entget

carmenaz
25th May 2005, 08:30 pm
Hi guys,
I have one big problem and I need to solve it till friday :(
Well here it goes:
I need to write a program, which recreates outline:
1.In AutoCAD I make some drawing, hatch it and delete it's outline
2.Then I load the program and when I "touch" the hatch of a drawing, it recreates the outline of a figure...

I've got the entity, but The main problem is that for me it is difficult to recreate the outline, here take a look:

&#40;defun c&#58;out &#40; / &#41;
&#40;entget&#40;entlast&#41;&#41;
&#41;

Well I found Jimmy's Bergmark's Hatchb program, which do that what I need.
But it's too huge. I'm only 2-nd day programming with AutoLISP, it's kind of difficult to understand....

CarlB
25th May 2005, 08:44 pm
The hatchb program is an example of the size/complexity of a program to do what you want - create a boundary around a hatch entity. Now if the hatch was always a rectangle or circle, it could be much simpler.

If this assignment has been given to a beginner lisp class, due by Friday, the instructor doesn't realize what she/he is asking or you've misunderstood the assignment. I think you would need at least a year of extensive experience before tackling a project like this.

If you can break down the project into simpler steps/questions, we'll try to help you along.

carmenaz
25th May 2005, 08:54 pm
First of all:
The drawing is made from straight lines, and angle between lines is 90 degrees or it is pi/2 radians

It looks something like this:
http://img90.echo.cx/img90/3886/untitled2fn.png

One main question: how can I recreate boundary?

Thanks CarlB for help
God bless you :wink:

CarlB
25th May 2005, 09:07 pm
You're welcome. I don't want to spoil your fun so I'll just give a few tips:

1. To see the entity data for a selected object, use "entsel". That returns the entity name and pick point in a list; use 'car' to get entity name. That leads to;
(setq Ename (car (entsel "\nPick object: ")))

2. Draw a polyline like the example, or draw one around the hatch. now use the code (above) to look at the entity data for the polyline and the hatch.

3. Notice the similar numbers in the one of the group code data, which represent coordinates.....

carmenaz
25th May 2005, 09:11 pm
Yeah
code is 10, when I use function entget
And another question:
Well, so what can I do with this entity name?
How can I use those coordinates to recreate boundary...
I'm sorry if I'm asking dump questions :unsure:

CarlB
25th May 2005, 09:41 pm
OK, you have a list of the entity's data, from;

(setq Edata (entget (car (entsel "\Pick hatch: "))))

You need to extract the vertices from the group code 10 data. You'll find these lisp functions useful in extracting information from lists:

assoc
car, cdr
nth
member
reverse

The brute force method would be to step through each item in the data list (using 'foreach' or 'repeat'), and if the first element(car) is a "10", add (cons) the coordinate to a second list.

When you have this second list complete (call it PlPoints), such as
((x1 y1 z1) (x2 y2 z2) (x3 y3 z3)...)

you can draw a polyline though these points with:

(command "pline")
(foreach x PlPoints
(command x)
)
(command "")

This should give you something to chew on for a while :)

Enjoy!

carmenaz
25th May 2005, 09:49 pm
Thank you CarlB
:thumbsup:
Now I'm chewing stuff you gave me :)

carmenaz
25th May 2005, 10:43 pm

&#40;defun c&#58;lew &#40; / e1 e2 &#41;
&#40;setq e1 &#40;entget &#40;car &#40;entsel "\Pick hatch&#58; "&#41;&#41;&#41;&#41;
&#40;foreach car&#40;10&#41; &#40;e1&#41; &#40;cons e1.e2&#41;&#41;
&#41;

get:

Pick hatch&#58; ; error&#58; bad function&#58; 10

I missed something... :oops:

carmenaz
25th May 2005, 10:56 pm

&#40;defun c&#58;lew &#40; / e1 e2 &#41;
&#40;setq e1 &#40;entget &#40;car &#40;entsel "\Pick hatch&#58; "&#41;&#41;&#41;&#41;
&#40;setq e2 &#40;assoc 10 e1&#41;&#41;
&#41;

I get only one coordinate

Pick hatch&#58; &#40;10 0.0 0.0 0.0&#41;

Missed something again...
:huh:

26th May 2005, 04:56 am

&#40;defun c&#58;lew &#40; / e1 e2 &#41;
&#40;setq e1 &#40;entget &#40;car &#40;entsel "\Pick hatch&#58; "&#41;&#41;&#41;&#41;
&#40;setq e2 &#40;assoc 10 e1&#41;&#41;
&#41;

I get only one coordinate

Pick hatch&#58; &#40;10 0.0 0.0 0.0&#41;

Missed something again...
:huh:

Hi carmenaz,
look like this

&#40;defun c&#58;lew &#40;/ ss sse hatch_pattern&#41;
&#40;prompt "\nPick hatch"&#41;
&#40;setq ss &#40;entsel&#41;&#41;
&#40;setq sse &#40;entget &#40;car ss&#41;&#41;&#41;
&#40;setq hatch_pattern &#40;cdr &#40;assoc 2 sse&#41;&#41;&#41;
etc.........
&#41;

((-1 . <Entity name: 157eea0>)
(0 . "HATCH")
(330 . <Entity name: 157ecf8>)
(5 . "AC")
(100 . "AcDbEntity") ; Subclass marker (AcDbHatch)
(67 . 0)
(410 . "Model")
(8 . "ACID BOTTLE") ; layer name
(100 . "AcDbHatch")
(10 0.0 0.0 0.0)
(210 0.0 0.0 1.0) ; Extrusion direction
(2 . "ANSI31") ; Hatch pattern name
(70 . 0) ; Solid fill flag (solid fill = 1; pattern fill = 0)
(71 . 1) ; Associativity flag (associative = 1; non-associative = 0)
(91 . 1) ; Number of boundary paths (loops)
(92 . 7)
(72 . 0)
(73 . 1)
(93 . 5)
(10 -109.063 51.9906 0.0)
(10 -161.063 51.9906 0.0)
(10 -161.063 -42.8274 0.0)
(10 -67.5629 -42.8274 0.0)
(10 -67.5629 9.17256 0.0)
(97 . 5)
(330 . <Entity name: 157ee00>)
(330 . <Entity name: 157ee28>)
(330 . <Entity name: 157ee08>)
(330 . <Entity name: 157ee30>)
(330 . <Entity name: 157ee48>)
(75 . 0)
(76 . 1)
(52 . 0.0)
(41 . 25.0)
(77 . 0)
(78 . 1)
(53 . 0.785398)
(43 . 0.0)
(44 . 0.0)
(45 . -2.20971)
(46 . 2.20971)
(79 . 0)
(47 . 0.676467)
(98 . 1)
(10 -127.647 10.0979 0.0))

CarlB
26th May 2005, 07:48 am
Yes, 'assoc' will give you only the first matching item. You need to dig deeper, thus the 'foreach' approach. Try this:

(foreach Item e1 ;;to step through the entity data list
(if (= (car Item) 10);;if group code 10 data
(setq Pt (cdr Item);;cdr strips the 10 from the xyz info
PtList (cons Pt PtList);;add point to point list
);setq
);if
);foreach

26th May 2005, 08:34 am
Yes, 'assoc' will give you only the first matching item. You need to dig deeper, thus the 'foreach' approach. Try this:

(foreach Item e1 ;;to step through the entity data list
(if (= (car Item) 10);;if group code 10 data
(setq Pt (cdr Item);;cdr strips the 10 from the xyz info
PtList (cons Pt PtList);;add point to point list
);setq
);if
);foreach

yes like that to find assoc 10,or you can try this

&#40;defun massoc &#40;key alist / nlist&#41;
&#40;foreach x alist
&#40;if &#40;eq key &#40;car x&#41;&#41;
&#40;setq nlist &#40;cons &#40;cdr x&#41; nlist&#41;&#41;&#41;&#41;
&#40;reverse nlist&#41;&#41;

&#40;setq ss &#40;ssget "x" '&#40;&#40;0 . "HATCH"&#41;&#41;&#41;&#41;
&#40;setq cnt 0&#41;
&#40;setq ssn &#40;ssname ss cnt&#41;&#41;
&#40;setq sse &#40;entget ssn&#41;&#41;
&#40;setq ptlst &#40;massoc 10 &#40;entget ssn&#41;&#41;&#41;

carmenaz
26th May 2005, 02:58 pm
Woow, so much good tips
Thank you guys :wink:

carmenaz
26th May 2005, 04:27 pm
I use this:

&#40;defun c&#58;lew &#40; / e1 PtList Item n pt &#41;
&#40;setq e1 &#40;entget &#40;car &#40;entsel "\Pick hatch&#58; "&#41;&#41;&#41;&#41;
&#40;setq PtList nil&#41;
&#40;foreach Item e1
&#40;if &#40;= &#40;car Item&#41; 10&#41;
&#40;setq Pt &#40;cdr Item&#41;
PtList &#40;cons Pt PtList&#41;
&#41;
&#41;
&#41;
&#40;foreach pt Ptlist
&#40;command "pline" ptlist&#41;
&#41;
&#41;

And I get:

Command&#58; lew
Pick hatch&#58; pline
Specify start point&#58;
Command&#58; pline
Specify start point&#58;
Command&#58; pline
Specify start point&#58;
Command&#58; pline
Specify start point&#58;
Command&#58; pline
Specify start point&#58;
Command&#58; pline
Specify start point&#58;
Command&#58; nil

Missed something again... it needs so little to be completed..
Sorry for my english, it isn't so good as yours :roll:

CarlB
26th May 2005, 06:17 pm
Your pline drawing portion is not right...

(command "pline");;starts the pline command

(foreach pt PtList ;;steps through each item, assign item to "pt"
(command pt);;feeds the "pt" to the pline command
);;end the foreach
(command "");;feeds a return, ending thee pline command

carmenaz
26th May 2005, 06:25 pm
Thank you CarlB, it actually recreates boundary :wink:
But there's another problem: two lines of boundary goes to ucs point (0,0,0) here take a look:

http://img97.echo.cx/img97/3016/untitled7yq.png

Interesting, of course I can draw graph at the ucs point (0,0,0)
It should work :lol:

CarlB
26th May 2005, 06:43 pm
We're getting close now :)

Apparently the hatch code has a first "group code 10" entry which represets its elevation. So you need to ignore that one.

One way to do that would be to trim the front off the original data list.

(setq First10 (assoc 10 Edata ));;returns first group 10 item
(setq RemList (member First10 Edata));returns list beginning with First10
(setq TrimList (cdr RemList));returns all but first item

Now work with this list to get the GC 10 items

carmenaz
26th May 2005, 07:14 pm
Hmm, still same problem, :(

(defun c:lew ( / First10 RemList TrimList e1 PtList Item n pt )
(setq e1 (entget (car (entsel "\Pick hatch: "))))
(setq First10 (assoc 10 e1 ));;returns first group 10 item
(setq RemList (member First10 e1));returns list beginning with First10
(setq TrimList (cdr RemList));returns all but first item
(setq PtList nil)
(foreach Item e1
(if (= (car Item) 10)
(setq Pt (cdr Item)
PtList (cons Pt PtList)
)
)
)
(command "pline")
(foreach pt PtList
(command pt)
)
(command "")
)

:oops:

CarlB
26th May 2005, 07:24 pm
..because your code continues to use "e1" rather than "trimlist"

After

(setq TrimList (cdr RemList));returns all but first item

add the following line to replace "e1" list with "trimlist"

(setq e1 Trimlist)

To help debug your routines, you can check what the value of variables are after you run the routine. For example to see what "trimlist" is, type "!trimlist" (without quotes, with exclamation point) on the command line.

carmenaz
26th May 2005, 08:09 pm
That's it :

(defun c:lew ( / First10 RemList TrimList e1 PtList Item n pt )
(setq e1 (entget (car (entsel "\Pick hatch: "))))
(setq First10 (assoc 10 e1 ));;returns first group 10 item
(setq RemList (member First10 e1));returns list beginning with First10
(setq TrimList (cdr RemList));returns all but first item
(setq e1 Trimlist)
(setq PtList nil)
(foreach Item e1
(if (= (car Item) 10)
(setq Pt (cdr Item)
PtList (cons Pt PtList)
)
)
)
(command "pline")
(foreach pt PtList
(command pt)
)
(command "")
)

I did it, but there's the same problem....
I feel so terrible asking so many questions.... :oops:

CarlB
26th May 2005, 08:50 pm
Well what do you know, there is another "group 10" item lurking in the hatch data. The last group 10 is the pick point used in creating the hatch. So you need to ignore that point as well. Now how do you remove the last point from a list (will actually be the first point in PtList since it was created by adding points to the front of a list while stepping through entitity data). So before drawing the pline, add a line (setq PtList (cdr ptlist)) which returns a list with the first item removed.

CarlB
26th May 2005, 08:54 pm
Oh and one more thing, the drawn polyline does not close. So just revise the last line -(command "")- with the extra entry to close the polyline.

carmenaz
26th May 2005, 09:16 pm
Now I'm totally confused :oops:

(defun c:lew ( / First10 RemList TrimList e1 PtList Item n pt )
(setq e1 (entget (car (entsel "\Pick hatch: "))))
(setq First10 (assoc 10 e1 ))
(setq RemList (member First10 e1))
(setq TrimList (cdr RemList))
(setq e1 Trimlist)
(setq PtList nil)
(foreach Item e1
(if (= (car Item) 10)
(setq Pt (cdr Item)
PtList (cons Pt PtList)
)
)
)
(setq PtList (cdr ptlist))
(command "pline")
(foreach pt PtList
(command pt)
)
(command "")
)

And take a look what I get:

http://img216.echo.cx/img216/2943/untitled8mv.png

There is missing one edge...
:oops:

CarlB
26th May 2005, 09:34 pm
In case you didn't notice my double post above, I anticipated this question and replied just before your last post.

carmenaz
26th May 2005, 09:39 pm
Oh My God It works :shock:
Thank you very much CarlB for your patience and for your help
God bless you
:wink: