Hi all,
Ok, I've made a lot of progress in the last few months. My current snag point is converting from using mdlText_create functionality to using TextBlocks.
Summary:
I've found many examples of how to add text to the active design file. This program creates several files from a common seed. Line geometry is being created (hooray) and updated properly in the files. When they are referenced manually into an Assembly file (the active design file), everything is working as it should.
For each file, I create a chart that identifies the model, who created it (ran the program), date/time stamp, and creates a generic revision block in case of any manual revisions that need to be added. This is populated using mdlText_create and sets level, color, line style, &c properties, which is then added to an Element Descriptor, which is appended to the workDGN after all of the bits are made for the rev block. The parent routine calls ldWriteLine(...) and ldWriteText(...) to create the rev block. Below is the base v8 routine that uses mdlText_create.
Public MSElementDescr *LDWriteText ( WChar *sss, /* String to print */ double sTS, /* Text size */ int sF, /* Font number */ int sJx, /* Horizontal Justification (0-4) */ int sJy, /* Vertical Justification (0-2) */ Dpoint3d *pt, /* Origin */ double xrot, /* Rotation about X axis */ double yrot, /* Rotation about Y axis */ double zrot, /* Rotation about Z axis */ UInt32 *color, /* Text Color */ UInt32 *weight, /* Text Weight */ MSElementDescr *addDes ) { MSElement partSegment; MSElementDescr *partDescr; TextSizeParam txSize; TextParam txParm; RotMatrix iMatrix, rMatrix; txSize.mode = TXT_BY_TILE_SIZE; txSize.size.width = sTS; txSize.size.height = sTS; txSize.aspectRatio = fc_1; txParm.font = sF; txParm.just = (sJx > -1 ? sJx * 3 + sJy : TXTJUST_CC); txParm.style = 0; txParm.viewIndependent = 0; mdlRMatrix_getIdentity(&iMatrix); mdlRMatrix_rotate(&rMatrix, &iMatrix, xrot, yrot, zrot); if (mdlText_create(&partSegment, NULL, sss, pt, &txSize, &rMatrix, &txParm, NULL) == SUCCESS) { mdlElement_setSymbology(&partSegment, color, weight, NULL); if (addDes == NULL) { mdlElmdscr_new(&partDescr, NULL, &partSegment); return partDescr; } else { partDescr = mdlElmdscr_appendElement(addDes, &partSegment); return partDescr; } } }
This code is what's used to add the text to the complex element.
I'm attempting to update this code, limiting the changes to the function itself. As mentioned, I have good examples of creating TextBlock elements. I think I've got the element creation bits down, but I can't seem to find sample code that takes the EditElement (or EditElementHandle) and appends it to an Element Descriptor to make it a complex element.
I'm trying to use the API documentation and searching examples, but that's slow going (as manual searches are), so I thought I'd drop something here to see if anyone has a "Oh yeah, it's dead easy, look at this..." response.
I know I probably don't have enough information here, but I don't know what else to add. If I knew how to convert the EEH to a Part Descriptor, or append it to one, I think that would push me over the hump.
Thanks,
Gary
Hi Gary,
at first, be aware you asked in general Developer and Programming forum. I recommend to move your question to MicroStation Programming forum. To move existing discussion to another forum, use More > Move tool, available under your original post.
Also, please follow the best practices and always specify used product and its exact version. Although probably not crucial for this specific discussion, it's generally recommended to share the information always.
Gary Shay said:Old v8 Application creates complex elements out of lines, line strings, ellipses, shapes, and text
What "complex elements"? Please be more specific, there are many "complex elements" in MicroStation (see ComplexHeaderDisplayHandler struct inheritance graph). Are final elements (unnamed) cells?
Gary Shay said:CE uses textBlocks, can't reuse the old code.
Not only text related code can't be reused ;-) And in many other examples (nearly always), to stick with old C-style code makes things much more complicated, when new OOP C++ classes can handle the same tasks easily.
Gary Shay said:but I can't seem to find sample code that takes the EditElement (or EditElementHandle) and appends it to an Element Descriptor to make it a complex element.
I do not recall such example as well, probably because it does not make any sense: When you have (Edit)ElementHandle and related Handler, you have everything you need, packed into well described classes. To convert it to element descriptor only makes situation probably more complicated.
Gary Shay said:limiting the changes to the function itself.
In my opinion (but I know nothing about the application and its context) it is generally wrong idea, requiring more effort than necessary.
What about to do it in opposite way? Because it is simple to create EditElementHandle from element descriptor, what about to always work with Handlers. Functional and working old code can be used to obtain descriptors (and to create Handlers from them). New / rewritten functionality returns handles automatically, which should make the whole process clear and simple. At the end, it can be packed e.g. using NormalCellHeaderHandler.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Jan -
Thanks for the reminder/suggestions. I think I moved/fixed it ok.
My last foray into MDL development was some minor enhancements around 2001 for Microstation 7.
Jan Šlegr said:What "complex elements"? Please be more specific, there are many "complex elements" in MicroStation (see ComplexHeaderDisplayHandler struct inheritance graph). Are final elements (unnamed) cells?
What I mean by "Complex Elements" is that it aggregates a bunch of bits (lines and text) into one element descriptor for the title block and writes that as a single MSElementDescriptor. While I can't be sure (it's been 20+ years since I developed it), I wrote it to write things in chunks and output to the file to minimize I/O, which was a consideration at the time. But I've slept a lot since then, so I could be making the reason up at this point. Are they unnamed cells? I don't think so - they're just a chain of elements, if that's a thing any more. It seems to be working.
Undoubtedly the element handle is the better option. You can then write the element using a function similar to mdlWorkDgn_write(...)?
There's many things that would have to change to use handlers that I could avoid if we can append using the element descriptors. If there is no other way, then maybe what I need to do is assemble the text bits into handlers and add the current MSElementDescr items as is, then the text as a separate element using the handler(s).
I'm assuming that there's a way to add the EEH to a work file? How does one write text to a work file?
Gary Shay said:What I mean by "Complex Elements" is that it aggregates a bunch of bits (lines and text) into one element descriptor for the title block and writes that as a single MSElementDescriptor
Don't let Brien Bastings read that!
I have no idea what happens when you write an element descriptor chain. I suggest that you create a normal cell header and append your elements to that.
Gary Shay said:Undoubtedly the element handle is the better option. You can then write the element
ElementHandle is a C++ smart pointer that wraps MSElementDescr. EditElementHandle.AddToModel() does what you want.
ElementHandle
MSElementDescr
EditElementHandle.AddToModel()
Regards, Jon Summers LA Solutions
Gary Shay said:My last foray into MDL development was some minor enhancements around 2001 for Microstation 7.
ok, so my advice is: Do not even try to remember what you knew at this time, because nearly everything has changed. And even when some old approach still works and can be used, it is probably wrong.
CE API is about object abstraction: Do not care about data persistence, use Handles (data representation) and Handlers + Queries (tools to access data). Every time you need element descriptor, something is wrong in used design or implementation.
Another typical problem of developers is that DGN element type != API class. Again, it's about abstraction, and proper handler takes care to persist (save) data, represented by a handle, in the right way. To demonstrate it, think about cell: it can be used to represent graphic cell, grouped elements (unnamed cell), grouped holes, SmartSolid, annotation (label with annotation dimension) etc. In API, when proper handlers are used, they ensure data is persisted right.
Gary Shay said:What I mean by "Complex Elements" is that it aggregates a bunch of bits (lines and text) into one element descriptor for the title block and writes that as a single MSElementDescriptor.
I agree with Jon, and I am sure a ghost of data and code quality comes to haunt you.
I think it was not valid approach even in V7 era, but DGN format and MicroStation itself has always be tolerant to different types of developers' sins.
Gary Shay said:I don't think so - they're just a chain of elements, if that's a thing any more.
It's not possible. Even in DGN V7, complex element must start with complex header, which can be ComplexString (chain), ComplexShape or CellHeader. Today, complex elements are represented by more classes (see the graph I mentioned earlier), but the concept is still the same in DGN V8 as was in DGN V7.
Gary Shay said:It seems to be working.
It would be interesting to have the original DGN V7 file and to use "element analyze" tool to check how the descriptor is persisted.
Gary Shay said:You can then write the element using a function similar to mdlWorkDgn_write(...)?
Forget "work DGN", there is DgnFile object available that can be used to access (load, create...) models, and consequently to use EditElementHandle to add element to the model.
I recommend to read DgnFile Struct Reference and related chapters (Working With Models, EditElementHandle Struct Reference etc.) There are plenty of useful information available.
Gary Shay said:There's many things that would have to change to use handlers that I could avoid if we can append using the element descriptors.
As described in EditElementHandle Struct Reference chapter, when you have valid Element Descriptor, it's simple to create EditElementHandle (and e.g. to compose more ElementHandles to more complex element and to add it to a model).
Gary Shay said:If there is no other way, then maybe what I need to do is assemble the text bits into handlers and add the current MSElementDescr items as is, then the text as a separate element using the handler(s).
What works now (although I assume it's dirty code probably) and product ElementDescriptor, use to create EditElementHandles. What must be converted to CE API, create as EditElementHandles. Compose all of them to required object.
Gary Shay said:I'm assuming that there's a way to add the EEH to a work file?
There is no "work file". When you do not want to use active model, use DgnFile object to open a file, load (or create) model and add elements to it. No difference between (active) model object and model object, opened directly at background.
I did not try it in C++ yet, but I did couple of tests in NET and it worked fine.
Ok, I get it now. I had a disconnect. Let me see if I have the right idea / process. Details aren't that important at this point - just trying to make sure I have the big picture. I realize that there are some holes here.
Here's the current process (written for old MDL version)
The new method to do the same is similar but using the DgnFile object.
There's plenty I have to work out here - probably quite a bit with the element attributes (old MDL language) in the new world, like can I string together all the bits that use the same color, weight, level, etc. and add them at once or can I add them back and forth without incurring processing overhead?
It seems like the general logic is the same, but the old one (apparently?) used some sketchy bits that maybe weren't a good idea then and shouldn't be used anymore. I just wasn't seeing it. It's fine - this stuff was built on code written ca. 1993 for Microstation J that has continued to work until CE. Maybe not fine, maybe on the edge of collapse, but still worked for v8i SS10 and didn't seem to cause any issues that were reported.
One more comment: I recommend to start with EditElementHandle Struct Reference chapter in MicroStationAPI documentation. It explains an element lifecycle and provide plenty of useful information how handle and element descriptor relationship including code snippets.
Regards,