Page 1 of 1

How to add an entity based on a symbol

PostPosted: Sun Jan 20, 2008 5:27 pm
by shovavnik
Hi all,

I have a symbol file that I need to add to a drawing using D4D and then create one or more entities based on the symbol.

The symbol file is located at:
C:\DataCAD 12\Symbols\MySymbol.dsf

Using sym_read, I've managed to add the symbol to the drawing, but I can't figure out how to create the entity.

I've tried this and other variations:
Code: Select allsymread('C:\DataCAD 12\Symbols\MySymbol', 'MySymbol', sym);
ent_init(ent, entsym);
ent.symstart := sym.addr;
ent_add(ent);


But none of them seem to work. Does anyone have any ideas or an example of how to do it correctly?

By the way, it seems that if there is another symbol in the symbol library with the same name (e.g, MySymbol), it will ALSO be added to the drawing, even though a full path is specified in sym_read. Does that make sense?

Regards,
shovavnik

PostPosted: Mon Jan 21, 2008 9:01 am
by Jon C. Hubart
I'm am not yet familiar with the D4D variations but in classic DCAL I used the following to insert a single instance of a symbol:
Code: Select allsettran (arrowmat, sympos.x, sympos.y, 0.0);
ent_init (ent, entsym);
ent.symname := sym.name;
ent.symaddr := sym.addr;
ent.symmod := arrowmat;
ent_add  (ent);
ent_rotate (ent, sympos, ang1);
ent_enlarge (ent, sympos, globscale, globscale, globscale);
ent_update (ent);
ent_draw (ent, drmode_white);

PostPosted: Mon Jan 21, 2008 10:10 am
by devinder
You just need to specify the name of symbol when adding entity. DataCAD will automatically look up the addr of the symbol and assign it to ent.symstart.

Code: Select allent_init(ent, entsym);
ent.symname := 'C:\DataCAD 12\Symbols\MySymbol';
ent_add(ent);

PostPosted: Thu Jan 24, 2008 6:38 pm
by shovavnik
Sorry it took me so long to get back to you. Thanks for the help!

Devinder:
I didn't realize the symname could take a path. From the examples I saw, it always takes just the file name or symbol name.

From what I can see, all 4 of these lines are necessary to add a symbol from a path (as opposed to a symbol from the library?) to a drawing. Without sym_read, it doesn't work.

Code: Select allsymread('C:\DataCAD 12\Symbols\MySymbol', 'MySymbol', sym);
ent_init(ent, entsym);
ent.symname := 'C:\DataCAD 12\Symbols\MySymbol';
ent_add(ent);


However it only seems to add the reference to the symbol and doesn't add it to the drawing surface.


Jon:
I thought your example would help me out in that regard, but I wasn't able to get it to work.

That is, it doesn't look like the entity is actually added to the drawing surface.

How do you know which modmat to use? (from the view? from the entity? from somewhere else?)

Also, how do you calculate the global scale?

PostPosted: Thu Jan 24, 2008 6:39 pm
by shovavnik
By the way, I noticed one discrepancy in the way symbol entities are loaded. I'm not sure if it's a bug or intentional. If you specify the path for a symbol whose file name is identical to the name of another symbol already in the library, BOTH symbol references are added to the entity, even though the full path was specified.

For example, if you run these statements:
Code: Select allent_init(ent, entsym);
ent.symname := 'C:\DataCAD 12\Symbols\SomeFolder\MySymbol';
ent_add(ent);


and you also have another symbol in the library at 'C:\DataCAD 12\Symbols\ADifferentFolder\MySymbol', then that statement will add both symbols to the drawing.

Is this a bug or by design? (I think it can be justified either way, but I just need to know what to prepare for...)

PostPosted: Fri Jan 25, 2008 9:10 am
by devinder
Code: Select allsymread(fname, symname: sym_str; var symbol: sym_type)

syread has 2 string parameters. The first one is filename. If this is absolute path DataCAD will use it, if it is relative path(or no path), DataCAD uses various path strings to make the path absolute. If the symbol is found and loads into drawing corrrectly, It then renames itself to symname, if sym_str is not empty string. On symname being empty the symbol name is same as fname. Ex.
Code: Select allsymread('C:\DataCAD 12\Symbols\MySymbol', '', sym)

If you look at the symbol structure, it stores only one string parameter. Once the path is stripped out from, symname , there is no way to tell from where the symbol was loaded. There are no validations on symbol name string. You can give any name with/without any path.

It is not feasible to match all entity parameters to all other entities in other symbols. Consider a drawing with 50 symbols each symbol averaging 50 entities. Now you wish to add a new symbol with 10 entities. The max number of computations to compare entities will be (10*50*50=25000) for it to consider that this symbol is not previously loaded.

PostPosted: Fri Jan 25, 2008 9:56 am
by shovavnik
So, if I understand correctly, instead of running the intensive comparison, DataCAD just adds all the symbols it can find with that name (e.g., 'MySymbol') to the drawing.

In other words, if I want to avoid ambiguity with symbols, it doesn't matter where the symbols are located, just their names.

Am I on the right track here?

PostPosted: Fri Jan 25, 2008 10:05 am
by shovavnik
I'm still trying to figure out how to actually draw the entity (that's based on the symbol).

I tried Jon's code and various variations (changing the scale, with and without rotation, etc.) but I can't seem to get it to work. I'm sure I'm just missing something simple and basic.

I know the entsym entity is added to the drawing.

Can anyone provide an example or point me to any reference that shows a full example of drawing a symbol entity?

PostPosted: Fri Jan 25, 2008 10:25 am
by devinder
Am I on the right track here?
Yes

Currently you are adding entity at (0,0,0), and you would need to call
Code: Select allent_draw(ent, drmode_white)
to draw the entity at DataCAD's absolute zero.

If you need to place an entity twice in size at the mouse click location with z base of 12 foot you would do:
Code: Select all...
cattran(ent.modmat, 2, 2, 2);
cattran(ent.modmat, l.getp.curs.x, l.getp.curs.y, 12 * onefoot);
ent_add(...);
ent_draw(...);

NOTE: Please see arrow macro for how to get input co-ordinates, if you have doubt.

PostPosted: Fri Jan 25, 2008 11:51 am
by shovavnik
I've got the state machine down pat (I think) and I'm already using getpoint to get the cursor location. Also, when you write "ent.modmat", I assume you mean "ent.Matrix". Let me know if I'm wrong.

I'm trying to add a symbol at the point {x: 8832, y: 6400, z: 0} by clicking on that point and catching the cursor point with getpoint.

When I trace using Delphi, I can see that after ent_init, ent.Matrix is 4x4 identity matrix. After using
Code: Select allcattran(ent.Matrix, pt.x, pt.y, pt.z);

ent.Matrix looks like
Code: Select all[1,0,0,0]
[0,1,0,0]
[0,0,1,0]
[8832, 6400, 0, 1]


The code I'm using to draw the entity is this:
Code: Select allent_init(ent, entsym);
ent.symname := symName;
ent_add(ent);
cattran(ent.Matrix, pt.x, pt.y, pt.z);
ent_update(ent);
ent_draw(ent, drmode_white);


But it's not working.

Also, I noticed that the coordinates of the point that I click on are always a bit different between what DataCAD says and what DCAL picks up. Instead of (508, 1016, 0) in DataCAD, for example, Delphi shows (512, 1280, 0). Could this be related? I ran the arrow example just to see if I could find something helpful from there, like you suggested, but it also has this discrepancy.

What am I missing?

PostPosted: Fri Jan 25, 2008 12:13 pm
by devinder
This should work. Could you email the sample source project to techsupport@datacad.com along with the symbol you are trying to load, and I will take a look at it.

PostPosted: Fri Jan 25, 2008 12:43 pm
by shovavnik
I sent the email with the project. Let me know if it doesn't come through.

PostPosted: Mon Jan 28, 2008 1:37 pm
by shovavnik
In case anybody else has issues similar to this, the following code works.

This code:
1. loads a symbol from a DSF file,
2. adds an instance of the symbol to the drawing (if it doesn't already exist in the drawing),
3. creates a symbol entity based on the symbol,
4. performs manipulation(s) on the symbol entity,
5. draws the symbol entity at point pt.

Code: Select allif sym_read(symPath, symName, sym) = 0 then // symPath should not contain the file extension
begin
  ent_init(ent, entsym);
  ent.symname := symName; // use symPath if you want to or if symName is empty
  ent_add(ent);
  cattran(ent.Matrix, pt.x, pt.y, pt.z); // translate the symbol to point pt
  // perform additional matrix operations if necessary for rotation, scale, etc.
  ent_update(ent);
  ent_draw(ent, drmode_white);
end;


HTH

PostPosted: Mon Jan 28, 2008 3:56 pm
by devinder
You can update matrix before adding entity to the database too, to avoid the need of calling ent_update and possibly saving one Undo Recording internally for ent_update.

shovavnik wrote:
Code: Select allif sym_read(symPath, symName, sym) = 0 then // symPath should not contain the file extension
begin
  ent_init(ent, entsym);
  ent.symname := symName; // use symPath if you want to or if symName is empty
  cattran(ent.Matrix, pt.x, pt.y, pt.z); // translate the symbol to point pt
  ent_add(ent);
  ent_draw(ent, drmode_white);
end;


HTH