Understanding the output of the entget function - autocad

I am using the entget function to get data about a polygon from the sketch in purpose of creating formula that shows how to calculate its area.
Therefore I need to understand the output of entget, an example of entget output :
(
(-1 . <Entity name: 7ef043b0>)
(0 . "LWPOLYLINE")
(330 . <Entity name: 7ef01f80>)
(5 . "2CE")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbPolyline")
(90 . 3)
(70 . 1)
(43 . 0.0)
(38 . 0.0)
(39 . 0.0)
(10 93.1128 191.34)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(10 83.1128 191.34)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(10 83.1128 202.104)
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(210 0.0 0.0 1.0)
)
The idea is that the number -1 ressemble a property for the polyline (its entity name by the way).
The number 10 ressembles a vertex/corner.
I cant figure out the rest of the properties.
Why do I need this? I can't differentiate between an triangle and a corner of a circle if I just used vertices/corners and their number.
Thank you for your help.

DXF data returned by the AutoLISP entget function is an association list in which the first element of each item (the key) corresponds to a DXF group, and the associated value corresponds to the value held by that group.
Each group represents a property of the entity, with the properties becoming more specific to the type of entity being described as you traverse the DXF data list.
The DXF groups at the start of the list, such as the entity type (DXF group 0) or entity handle (DXF group 5) are common to every database object. These are followed by properties of the base class (in this case AcDbEntity) under which you will find the layer (DXF group 8) and drawing layout (DXF group 410), and finally, properties of the object class (in this case AcDbPolyline) under which you will find properties pertinent to the type of object, such as the polyline vertices (DXF group 10), number of vertices (DXF group 90) etc.
You may find a full DXF reference here. Note that this reference includes both graphical & non-graphical entities (such as layer definitions and dictonaries).
A DXF reference for the DXF groups associated with an LWPOLYLINE entity may be found within the ENTITIES section of the reference here.
You may also find my Entity List program useful when interpreting DXF data, as this program will format the data returned by the entget function into a readable output, and will include all subentities which follow the primary entity, along with any Extended Entity Data (xData) attached to such entities.
Aside, in response to the comment on your question: please note that DXF group 5 contains the entity handle, which bears no relation to the type of entity. This is purely an identifier which is unique within a drawing and persistent for the life of the drawing.

Related

In Visual FoxPro, how does one incorporate a SUM REST command into a SCAN loop?

I am trying to complete a mortality table, using loops in Visual Foxpro. I have run into one difficulty where the math operation involves doing a sum of of all data in a column for the remaining rows - this needs to be incorporated into a loop. The strategy I thought would work, nesting a SUM REST function into the SCAN REST function, was not successful, and I haven't found a good alternative approach.
In FoxPro, I can successfully use the SCAN function as follows, say:
Go 1
Replace survivors WITH 1000000
SCATTER NAME oprev
SKIP
SCAN rest
replace survivors WITH (1 - oprev.prob) * oprev.survivors
SCATTER NAME oprev
ENDSCAN
(to take the mortality rates in a table and use it to compute number of survivors at each age)
Or, say:
Replace Yearslived WITH 0
SCATTER NAME oprev1
SKIP
SCAN rest
replace Yearslived WITH (oprev1.survivors + survivors) * 0.5
SCATTER NAME oprev1
ENDSCAN
In order to complete a mortality table I want to use the Yearslived and survivors data (which were produced using the SCANs above) to get life expectancy data as follows. Say we have the simplified table:
SURVIVORS YEARSLIVED LIFEEXP
100 0 ?
80 90 ?
60 70 ?
40 50 ?
20 30 ?
0 10 ?
Then each LIFEEXP record should be the sum of the remaining YEARSLIVED records divided by the corresponding Survivors record, i.e:
LIFEEXP (1) = (90+70+50+30+10)/100
LIFEEXP (2) = (70+50+30+10)/80
...and so on.
I attempted to do this with a similar SCAN approach - see below:
Go 1
SCATTER NAME Oprev2
SCAN rest
replace lifeexp WITH ((SUM yearslived Rest) - oprev2.yearslived) / oprev2.survivors
SCATTER NAME oprev2
ENDSCAN
But here I get the error message "Function name is missing)." Help tells me this is probably because the function contains too many arguments.
So I then also tried to break things down and first use SCAN just to get all of my SUM REST data, as follows:
SCAN rest
SUM yearslived REST
END SCAN
... in the hope that I could get this data, define it as a variable, and create a simpler SCAN function above. However, I seem to be doing something wrong here as well, as instead of getting all necessary sums (first the sum of rows 2 to end, then 3 to end, etc.), I only get one sum, of all the yearslived data. In other words, using the sample data, I am given just 250, instead of the list 250, 160, 90, 40, 10.
What am I doing wrong? And more generally, how can I create a loop in Foxpro that includes a function where you Sum up all remaining data in a specific column over and over again (first 2nd through last record, then 3rd through last record, and so on)?
Any help will be much appreciated!
TM
Well you are really hiding the important detail, your table's structure, sample data and desired output. Then it is mostly guess work which have a high chance of to be true.
You seem to be trying to do something like this:
Create Cursor Mortality (Survivors i, YearsLived i, LifeExp b)
Local ix, oprev1
For ix=100 To 0 Step -20
Insert Into Mortality (Survivors, YearsLived) Values (m.ix,0)
Endfor
Locate
Survivors = Mortality.Survivors
Skip
Scan Rest
Replace YearsLived With (m.Survivors + Mortality.Survivors) * 0.5
Survivors = Mortality.Survivors
Endscan
*** Here is the part that deals with your sum problem
Local nRecNo, nSum
Scan
* Save current recnord number
nRecNo = Recno()
Skip
* Sum REST after skipping to next row
Sum YearsLived Rest To nSum
* Position back to row where we started
Go m.nRecNo
* Do the replacement
Replace LifeExp With Iif(Survivors=0,0,m.nSum/Survivors)
* ENDSCAN would implicitly move to next record
Endscan
* We are done. Go first record and browse
Locate
Browse
While there are N ways to do this in VFP, this is one xbase approach to do that and relatively simple to understand IMHO.
Where did you go wrong?
Well, you tried to use SUM as if it were a function, but it is a command. There is SUM() function for SQL as an aggregate function but here you are using the xBase command SUM.
EDIT: And BTW in this code:
SCAN rest
SUM yearslived REST
ENDSCAN
What you are doing is, starting a SCAN with a scope of REST, in loop you are using another scoped command
SUM yearslived REST
This effectively does the summing on the REST of records and places the record pointer to bottom. Endscan further advances it to eof(). Thus it only works for the first record.

Constraining an expression in LMFIT to 0

I am just beginning to use LMFIT on a manetostatic problem and wish to enforce that a dot product of vectors be zero. I have defined the parameters (vector components) n0_x, n0_y, n0_z, a0_x, a0_y, and a0_z and given them initial values. Then I define the parameter:
param.add('a0dotn0',expr='n0_x*a0_x+n0_y*a0_y+n0_z*a0_z')
but a0dotn0 is given the value of the dot product of the initial vectors a0 and n0. How do I enforce the constraint that a0dotn0 is always zero?
The standard recommendation is to provide a complete example to show what you are trying to do. Without that, anyone trying to help you has to guess what you're doing and might get it wrong.
If you're defining parameters with something like
params = lmfit.Parameters()
param.add('n0_x', 1.0)
param.add('n0_y', 0.9)
param.add('n0_z', 0.8)
param.add('a0_x', 0.5)
param.add('a0_y', 0.4)
param.add('a0_z', 0.6)
and want these values to be constrained such that n0_x*a0_x+n0_y*a0_y+n0_z*a0_z = 0 then the easiest way to change one of the parameters to be defined to satisfy that constraint, say by replacing that last parameter definition with
## a0_z = -(n0_x*a0_x + n0_y*a0_y)/n0_z
param.add('a0_z', expr='-(n0_x*a0_x + n0_y*a0_y)/n0_z')
You might want to ensure that n0_z cannot be zero.

Passing file name of a specified length in MATLAB

Problem in generating file names
I have around 4000 .txt files each containing three columns of data. I want to read all the 3 columns from a single file one at a time and then plot three values which correspond to x,y,z values on a contour plot.
These files are created at various time step. So a plot from one file will be a level curve and plots from all of them will give me a contour plot.
But the problem I want to do something which I can do in bash like this:
for n in `seq -f "%09g" 30001 200 830001`; do
./someFile$n.whateverFileFormat
done
How can I do this in matlab so that if I have let's say:
t-000030001.txt
1 2 3
......
......
......
t-0000320001.txt
2 4 5
. . .
. . .
. . .
and so on to
t-0008300001.txt
3 5 6
. . .
. . .
and on it goes.
I want to load all these files one at a time store the values in a infx3 array plot them on a contour plot and do this again and again for all the files so that I can have all of them on a single plot.
P.S. I need to reproduce something equivalent to that bash script mentioned above so as to load files appropriately then only I will be read from them
One way to get the list of file names is this:
fnames = arrayfun(#(num)sprintf('t-%09g.txt', num), 30001:200:830001, 'Uniformoutput', 0);
Let's have a closer look: 30001:200:830001 generates an array, starting at 30001, incrementing by 200, ending at 830001. sprintf generates a formatted string, and arrayfun applies the anonymous function passed as its first argument to each element of the array in its second argument (the sequence). The output is a cell array containing the file names.
EDIT
The solution above is equivalent to the following code:
ind = 30001:200:830001;
fnames = cell(numel(ind), 1);
for i = 1:numel(ind)
fnames{i} = sprintf('t-%09g.txt',ind(i));
end
This stores all the values in the a cell array.
Writing #(num)sprintf('t-%09g.txt', num) creates an anonymous function. The looping happens in arrayfun.

Read the annotations on a CT image

I have a CT image but some of the annotations i am not sure what do they stand for. These annotations are the following:
1) PP: HFS;
2) PRE
3) TI: 821.00 msec;
4) SP: -1372.30
5) 00564489, is this a patient ID?
Anybody can help me about this? Image can also be read [here]
1) PP: HFS : This is Patient Position: Head First, Supine
2) PRE: This could mean Previous study
3) TI : 821.00 msec - Could be Time Interval
4) SP: -1372.30 - This is Slice Position
5) 00564489, is this a patient ID? -- if this is next to patient name on right top corner.
Your best option is to get the user guide or help documentation of the application you are investigating. It should list what each label represents.

Very slow Object array manipulation in MATLAB

I'm trying to implement a 8 puzzle program using the manhattan heuristic using OOP in matlab, with each node represented by an object "state". However, i'm having lost of speed problems implementing an object array for queue. After lots of trial and error, this is the fastest i could go (i hate using global objects but it seems that any attempts at passing the array or using an object for it slows it down tremendously):
.classdef state < handle
. properties
. position; %3x3 array
. moves;
. blank;
. parent;
. prevmove;
. mdist;
. end
....
queue is preallocated
queue = repmat(state,1,5000);
.function newfront = q(item,front)
.global queue;
.if isempty(front)
. newfront = 1;
. queue(1) = item;
.else
. for i = front:-1:0
. if i == 0
. break;
. end
. a = item.mdist;
. b = queue(i).mdist;
. if (a < b)
. break;
. else
. queue(i+1) = queue(i);
. end
. end
. newfront = front + 1;
. queue(i+1) = item;
.end
.end
Using MATLAB profiler:
eightpuzzle 1 67.941 s 2.550 s
eightpuzzle>q 4722 59.657 s 59.657 s
....
118 queue(i+1) = queue(i); 2583916 29.064 s 48.7%
120 end 2583916 16.202 s 27.2%
114 b = queue(i).mdist; 2587318 4.357 s 7.3%
113 a = item.mdist; 2587318 2.783 s 4.7%
115 if (a < b) 2587318 2.721 s 4.6%
is there anyway to make it run faster? interesting thing to note was that by using
a = item.mdist;
b = queue(i).mdist;
if (a < b)
...
instead of
if (item.mdist < queue(i).mdist)
overall runtime was already halved.
Thanks!
I don't know if it might related to this topic about general OOP slowness in MATLAB:
Is MATLAB OOP slow or am I doing something wrong?
And here's yet another link about slow behaviour of handle classes, but it's likely fixed so far since the bug was reported years ago:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/288746
There is a large amount of memory overhead when using object arrays in MATLAB, just as in structure arrays. Each field of each array element is its own mxArray and that adds significant memory overhead. Consider using a 1x1 structure with non-scalar fields, rather than a 1xN structure with scalar fields - it will be substantially smaller in memory, and the access to each field will be much faster.
An example:
A 1x100 structure array with two scalar fields "a" and "b" requires (100*2) + 1 mxArray objects in memory.
A 1x1 structure array with two non-scalar fields "a" and "b" each of size 1x100 requires 3 mxArray objects in memory.
Your array of objects is very similar to a structure array, where the fields of each array element can be thought of as pointers. Let's say you have an object array "obj" that is 1xN with fields "a" and "b". Referencing the Kth object field's "a":
obj(K).a
This is an index operation and also an mxArray pointer dereference to the field "a".
I concede that using a scalar object would make your code less intuitive, but that's a trade-off you'll have to weigh.

Resources