Hi everyone,
I am trying to write an MDL for Microstation V8i (Select Series 4) which should transform the heights according to a certain height-modelling for different element-types.
I am using a Loop over all graphical Elements with a callback-function, which first creates an Duplicate of the MSElementDscr-Object
mdlElmdscr_duplicate(&newedP, edP);
first and afterwards calls the specific Transformation-function according to the element-type.
It works already for some Elements, like e.g. for Line_3d-Elements:
Private int HoehTrans_htransLine ( MSElementDescr **edPP // <=> Zeiger auf MSElementDescr-Objekt ) { int test1=FALSE, test2=FALSE; // Height-Transformation test1=test_transHPoint(&(*edPP)->el.line_3d.start); test2=test_transHPoint(&(*edPP)->el.line_3d.end); if(test1==TRUE && test2==TRUE) return TRUE; else return FALSE; }
The same thing should be done for Line_String_3d-Elements as well with the following Code:
Private int HoehTrans_htransLineString ( MSElementDescr **edPP // <=> Zeiger auf MSElementDescr-Objekt ) { int test=FALSE i; int pnum; DPoint3d** pList; // Speicher fuer Punktliste allokieren pnum=(*edPP)->el.line_string_3d.numverts; pList= (DPoint3d**) calloc(pnum, sizeof(DPoint3d*)); for(i=0; i<pnum; i++) pList[i]= (DPoint3d*) calloc(1, sizeof(DPoint3d)); // Hoehen-Transformation test=HoehTrans_transHList(&(*edPP)->el.line_string_3d.vertice, pnum); if(test==TRUE) return TRUE; else return FALSE; }
The connected height-transformation test-function Looks like this:
Private int test_transHList ( DPoint3d** pointPL, //<=> IN/OUT: zu transformierende DPunkt3d-Liste int pnum // => IN: Anzahl der Punkte in Liste ) { double dh=150.0; int ret=FALSE, i; if(pointPL!=NULL) { for(i=0; i<pnum; i++) pointPL[i]->z+=dh; ret=TRUE; } return ret; }
My Problem is now, that I get an Compiler-error in the function "HoehTrans_htransLineString" for the Line
- test=HoehTrans_transHList(&(*edPP)->el.line_string_3d.vertice, pnum);
that says:
"conversion of Parameter 1 from 'DPoint3d (*)[1]' in 'DPoint3d **' not possible"
Because the number of Vertices in the Element is not only "ONE", why is the '(&(*edPP)->el.line_string_3d.vertice'-Parameter of the LineString-Element not a field-pointer 'DPoint3d**' ??
Did I understand something wrong, or is it just a simple error in the Code?
In case of the Line-Element I rewrite finally in the callback-function the changed MSElementDscr-Object to file using and would like to do that with the LineString in the same way:
mdlElmdscr_rewrite(newedP, NULL, filePos);
Many thanks in advance for your help!
Best regards,
Ines Wieland
Ines Wieland said:The connected height-transformation test-function
You're digging too deep into the element structure. Use the tools available to you that use the power of the API. The key word in your above statement is 'transformation'. You can use a Transform to move any type of element.
In other words, don't do this...
double dh=150.0; int ret=FALSE, i; if(pointPL!=NULL) { for(i=0; i<pnum; i++) pointPL[i]->z+=dh; ret=TRUE; }
Prefer to make a transform and apply it to your element...
#include <mselmdsc.fdf> #include <mstmatrx.fdf>
Transform transform; mdlTMatrix_getIdentity (&transform); const double elevate = 150.0; DPoint3d offset = { 0., 0., elevate }; mdlTMatrix_setTranslation (&transform, &offset);
...
mdlElmdscr_transform (newedP, &transform);
Note that this approach is higher-level and you don't need to know about the element vertices or how they are stored.
Regards, Jon Summers LA Solutions
Hi Jon,
thanks for your answer, but you got me wrong: I only used this simple test-function (with only adding a constant height), because the real function is much more complicate and depending on the position of each point, so there is no possibility to move the whole element, but to adjust the height for each coordinate.
The way you described is already used for Point-Elements (like Cells and Texts), but the height-correction varies in the area, like an area-function dh=f(x,y), which is already implemented, therefore for Lines, Linestrings, Shapes ... I need to manipulate the height of each vertex separateley
Ines Wieland said:I need to manipulate the height of each vertex separateley
My earlier comment still stands: use a higher-level C++ approach and eschew the C-style memory allocation.
Read this article about the C++ standard library and using std::vector<DPoint3d>.
std::vector<DPoint3d>
#include <vector> // Standard Library header for vector template class typedef std::vector<DPoint3d> DPoint3dCollection; // typedef clarifies subsequent code
void ExtractPoints (MSElement const* linearElement, DgnModelRefP modelRef) { int pointCount = mdlLinear_getPointCount (linearElement); DPoint3dCollection points (pointCount); // Ensure that the vector knows how many points it contains points.resize (pointCount); if (SUCCESS == mdlLinear_extract (&points[0], &pointCount, linearElement, modelRef)) { // Do something with points ... for (int i = 0; i != pointCount; ++i) { DPoint3d& point = points [i]; point.z = 1234.; } } // No need to free() anything }
Answer Verified By: Ines Wieland
Private int HoehTrans_htransLine( MSElementDescr **edPP // <=> Zeiger auf MSElementDescr-Objekt) { int test1=FALSE, test2=FALSE; // Height-Transformation test1=test_transHPoint(&(*edPP)->el.line_3d.start); test2=test_transHPoint(&(*edPP)->el.line_3d.end);
if(test1==TRUE && test2==TRUE) return TRUE; else return FALSE; }
^ The serious problem with this approach is that it doesn't update line element's range, so now you have a line element with end points that are potentially outside it's range and that will be the source of all kinds of problems.
As Jon points out, the standard approach to modification is to extract the information, update it, then feed it back to a create function where you supply the original element as the template.
HTH
-B