Hello,
I'm trying to write a function to create a dgn file and add some elements to it. This function receives a string to use it as name to create the file.
void createfile(char str[]){ int pFormat=DGNFILE_FORMAT_V8; //defining the format MSElementDescr *elmDP; //creating pointer to an element descriptor to be used to write into created file DgnModelRefP pModelRef; //defining a variable for default model mdlElmdscr_new (&elmDP, NULL, &oElm); // allocating an element to element discripto | for now, oElm is a global variable and it's MSElementUnion type mdlWorkDgn_createFile (&pModelRef, str, pFormat, MASTERFILE, SEED_CopyDefaultData, NULL, NULL, FALSE); // create dgn file method mdlWorkDgn_write (elmDP, NULL, pModelRef); // hoping this will copy oElm model into created file in previous line getFile(); //a function to do some task unrelated to this function mdlWorkDgn_saveChanges (pModelRef); //save the create file mdlWorkDgn_closeFile(pModelRef); //close created file }
I'm not sure if I understood this concept correctly or not and what I have in my function is based on the information I gathered on similar topics.
Can you tell me what I'm doing wrong here?
Regards,
Mohammad
Hi Mohammad,
Unknown said:I'm not sure if I understood this concept correctly or not
In my opinion there are two problems:
Unknown said:Can you tell me what I'm doing wrong here?
Unsorted notes:
Your function does too many things (so it breaks important rule "one function is responsible for one thing"). With a requirement to define variables at a beginning of block code it makes the code chaotic. I see two main tasks there: To create the file and to add an element. At least you have to test whether the file was created succesfully and to create the element only if the test is passed.
Why do you define int pFormat=DGNFILE_FORMAT_V8; if you use it only as parameter in one function? It's reduntant code.
Where is any test mdlElmdscr_new (&elmDP, NULL, &oElm); returned SUCCESS? In the rest of the code you work with element descriptor you know nothing about. BTW to use global variable in such simple code is evil and bad habbit in my opinion, I see no reason to write such code at all.
What mdlWorkDgn_write (elmDP, NULL, pModelRef); returns? Does it do anything or it returns 0. It's impossible to provide any advice if it's not told what your reports.
getFile(); //a function to do some task unrelated to this function ... It's so bad :-( You create (try to create) element, add it the work file and after it start to do something different not related to this function? You have to finish the operation (save changes, maybe to close the file) and to continue with other tasks.
To add element descriptor to model also function mdlElmdscr_addByModelRef can be used and I guess it's recommended as replacement for older mdlWorkDgn_write.
If anything goes wrong, you should check global variable mdlErrno, often it provides more detail information where the problem can be (it contains values like MDLERR_READONLY, MDLERR_BADELEMENT etc.).
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Unknown said:Why do you define int pFormat=DGNFILE_FORMAT_V8; if you use it only as parameter in one function? It's reduntant code.
I found this in another post in this community and just used it to get all my arguments for the function going.
Unknown said:At least you have to test whether the file was created succesfully and to create the element only if the test is passed.
I did a test on this but it's returning 0 for creating the file. However, the file is created in the location I specified.
mdlWorkDgn_write (&elmDP, NULL, pModelRef) is also returning 0.
Unknown said:Where is any test mdlElmdscr_new (&elmDP, NULL, &oElm); returned SUCCESS?
I added a test to confirm if succeeded or not, and it did return a non 0 value.
Unknown said:What mdlWorkDgn_write (elmDP, NULL, pModelRef);
This is also returning 0.
Unknown said:getFile(); //a function to do some task unrelated to this function ... It's so bad :-(
I removed it from my code.
Unknown said:To add element descriptor to model also function mdlElmdscr_addByModelRef can be used
I used this and it adds the element to target model. Although, if I have a loop to create multiple element of the same type and try to add this element to element descriptor and then to a file from descriptor, it only adds the last one. So, if the loop repeats 7 times, I only see the linestring which was created in the last time through the loop is added to target model.
this is how my loop looks like:
while(i < 7){ lsPoints[0].x = sxp; lsPoints[0].y = syp; lsPoints[1].x = exp; lsPoints[1].y = eyp; mdlLineString_create(&oElm, NULL, lsPoints,2); if(mdlElmdscr_new (&elmDP, NULL, &oElm)==0){ mdlElmdscr_addByModelRef(&elmDP,pModelRef); } i++; syp = syp + 200; eyp = eyp + 200; }
is there a way to save the active model with a different name rather than creating a new model, and copying all elements to it?
Unknown said:I added a test to confirm if succeeded or not, and it did return a non 0 value.
So this is the step that does not work correctly. Whatever below this line should not be treated as valid, if element descriptor was not created correctly.
It's your responsibility to check what value is returned and to analyze if MDLERR_BADELEMENT or something else.
Unknown said:Although, if I have a loop to create multiple element of the same type...
Please, follow the rule "new issue, new post". The topic of this discussion is how to create work file using mdlWorkDgn function.
Unknown said:is there a way to save the active model with a different name rather than creating a new model, and copying all elements to it?
The same rule, please post is as a new question. And I recommend also to explain what do you want to achieve, because waht you describe sounds more like simple Save as functionality.
Hello Jan,
Unknown said:So this is the step that does not work correctly. Whatever below this line should not be treated as valid, if element descriptor was not created correctly.
Just to be clear on this, if it returns 0, it means it was successful? the result of creating a element descriptor is not 0 in my case. If so, I had a misunderstanding and thought 0 means false and anything other than 0 and positive means true.
I opened created a new post for those two other questions.
Unknown said:if it returns 0, it means it was successful?
It's something you have to learn, otherwise you will not survive in cruel C world: It's C de facto standard that functions return 0 as "success return value". It's the same as with exe, they also should return 0 if they finished without problem or error.
But the right approach is to don't discuss if it's zero or whatever else value, because return value is exactly define for every function. E.g for mdlElmdscr_new it's Returns SUCCESS if a new element descriptor.... So it's not defined it's 0, but it's SUCCESS, which is macro defined in some header file.
It means the only correct test is
if (SUCCESS == mdlElmdscr_new(...)) { ... }
Unknown said:How can I check to see what has been recorded in MDLERR_BADELEMENT?
Nothing is recorded anywhere, it's only return code.
Unknown said:I couldn't find any information on how to handle MDLERR_BADELEMENT.
There is no one common approach or reason why this error is reported. It depends on the function that returns this code.
You have to check MDL documentation and try to understand why this error is reported. Often the problem is not in the function itself, but e.g. wrong or invalid parameter is used.
Unknown said:but it doesn't return SUCCESS at creating dng file.
If mdlWorkDgn_createFile does not return SUCCESS, I guess you have to check mdlErrno, because I don't see any explanation of other returned values in mdlWorkDgn_createFile documentation. What error is in mdlErrno? (values are defined in mdlerrs.h)