Hello,
In the SDK is the example "ViewInfoExample". I build it, but it's not working correctly.
If I change the Origin of the ACS in any View, the "View Info Description" doesn't show this change. Closing and reopening these windows doesn't help. "ACS origin:" is allways listed as "(0,0,0)".
/resized-image/__size/320x240/__key/communityserver-discussions-components-files/343173/ACSorigin_2D00_bug.jpg
I added in my own mdl-app a new line with the acs Name and I got the correct output for each view. But I'm not able to define new ACS's with my app.
How am I able to set a new ACS with my own Parameters and get the exsisting ACS-Information?
I saw the "mdlACS_"-Functions, but they are not well documented and without a example I'm lost at the moment.
Im running Windows 10, 64 Bit, VS Community 2017, Net Framework 4.6.2, MicorStation Connect Edition V.10.15.00.74 (German)
Best regards Ole Gottwald
Ole Gottwald said:I saw the "mdlACS_"-Functions, but they are not well documented
The SDK example ViewInfoExample uses the IAuxCoordSys class rather than the old mdlACS_api. If it doesn't work, perhaps Robert Hook can ask someone to diagnose it.
IAuxCoordSys
mdlACS_api
Ole Gottwald said:I saw the "mdlACS_"-Functions,
Those are probably wrappers around the IAuxCoordSys class.
Ole Gottwald said:they are not well documented
That's one reason why we need good examples.
Regards, Jon Summers LA Solutions
Hi Thanks for your fast answer at Sunday,
good to know, that the IAuxCoordSys class is today the way to go!
IAuxCoordSysP acs = viewInfo.GetAuxCoordinateSystem(); sTemp.Sprintf(L"ACS name: %s\n", acs->GetName()); sInfo += sTemp; sTemp.Sprintf(L"ACS description: %s\n", acs->GetDescription()); sInfo += sTemp; sTemp.Sprintf(L"ACS typeName: %s\n", acs->GetTypeName()); sInfo += sTemp; DPoint3d acsOrigin; acs->GetOrigin(acsOrigin); sTemp.Sprintf(L"ACS origin: (%d, %d, %d) \n", acsOrigin.x, acsOrigin.y, acsOrigin.z); sInfo += sTemp; RotMatrix acsRot; acs->GetRotation(acsRot); sTemp.Sprintf(L"Acs rotation (maxAbs): %d \n", acsRot.MaxAbs()); sInfo += sTemp; sTemp.Sprintf(L"ACS scale: %d", acs->GetScale()); sInfo += sTemp;
I changed a few lines to test the outputs. As far I can see, only the output of "ACS origin" is not working (always 0,0,0). With the Reset Button, there should be a new ACS defined, but this doesn't work. A new level gets created and the view is reseted to top view.
Best regards
Edit: The output of "scale" was "0". I don't know, if that is wrong.
Ole Gottwald said:only the output of "ACS origin"sTemp.Sprintf(L"ACS origin: (%d, %d, %d) \n", acsOrigin.x, acsOrigin.y, acsOrigin.z);
sTemp.Sprintf(L"ACS origin: (%d, %d, %d) \n", acsOrigin.x, acsOrigin.y, acsOrigin.z);
You're using an integer print format for a double variable. Try this...
sTemp.Sprintf(L"ACS origin: (%f, %f, %f) \n", acsOrigin.x, acsOrigin.y, acsOrigin.z);
Ole Gottwald said:The output of "scale" was "0"
sTemp.Sprintf(L"ACS scale: %.2lf", acs->GetScale());
Both C# and C++ provide 1D, 2D and 3D formatters: read this article. The formatters provide consistent formatting of values, take account of UORs-to-Master Units conversion, and do the right thing for area and volume calculations.
Answer Verified By: Ole Gottwald
Hello thx for your answer,
I copied the lines from the "ViewInfoExample.cpp" (from MicroStationSDK->examples->View->ViewInfoExample).
IAuxCoordSysP acs = viewInfo.GetAuxCoordinateSystem(); DPoint3d acsOrigin; acs->GetOrigin(acsOrigin); sTemp.Sprintf(L"ACS origin: (%d, %d, %d) \n", acsOrigin.x, acsOrigin.y, acsOrigin.z); sInfo += sTemp;
Maybe this should be changed there, too.
Ole Gottwald said:Maybe this should be changed there, too
Yes: there's nothing worse than an example that doesn't work! Robert Hook please note.
Most important were the origin values. Thank you for the hint with UORs.
But setting a new Name was shown in the example too, and would be nice to have.
acs->SetName(L"AcsName");
How can I set the new Name. My code to create an new ACS. I get a new one, but the Name-Field keeps empty.
IAuxCoordSysPtr acs = IACSManager::GetManager().CreateACS(); if (acs.IsValid()) { acs->SetOrigin(acsOrigin); acs->SetName(L"AcsName"); acs->SetRotation(acsRot); acs->SetType(ACSType::Rectangular); //acs->SetDescription(); //acs->SetDescription(); //acs->SetScale(); vInfo->SetAuxCoordinateSystem(acs.get()); }
Maybe again the wrong datatype, but I got no solution so far. I'm new to cpp obviously. So ignore the question, if it is to trivial. I will find out sooner or later :D have a good day!
Ole Gottwald said:How can I set the new Name
Set the value changes something in memory. To persist the new value, save the ACS: acs->SaveToFile (DgnModelRefP modelRef, ACSSaveOptions option).
acs->SaveToFile (DgnModelRefP modelRef, ACSSaveOptions option)
Because the example of "ViewInfoExample" is not working correctly and I wasn't able to find examples in this forum, I'll share my code here
A function to create a new ACS and set it as activ acs of a specific view (C++):
static void setAcs() { DgnModelRefP modelRef = mdlModelRef_getActive(); // get Active Model if (NULL == modelRef) return; const double uor = mdlModelRef_getUorPerMaster(modelRef); // get Units of Resolution RotMatrix acsRot; acsRot.InitIdentity() // define a Rotation Matrix DPoint3d acsOrigin = DPoint3d::From(99.0 * uor, 20.0 * uor, 30.0 * uor); // define a Origin in Master Units IAuxCoordSysPtr acs = IACSManager::GetManager().CreateACS(); // Create a ACS-Pointer if (acs.IsValid()) { acs->SetOrigin(acsOrigin); acs->SetName(L"Acs Name"); acs->SetRotation(acsRot); acs->SetType(ACSType::Rectangular); acs->SetFlags(ACSFlags::Default); acs->SetDescription(L"Acs Description"); acs->SetScale(1.0); acs->SaveToFile(modelRef, ACSSaveOptions::AllowNew); } // Add Information to the ACS-Pointer ViewportR vp = * IViewManager::GetManager().GetActiveViewSet().GetViewport(viewInfoTestData.viewNo); // Get ViewportReference : viewInfoTestData.viewNo is a int IACSManager::GetManager().SetActive(acs.get(), vp ); // sets the created ACS as Active in the View-Number }
In the documentation of the function IViewManager::GetViewport(int viewNum) the datatype is IndexedViewportP (IViewManager). But u can use the datatype Viewport instead.
You need a variable vp with datatype ViewportR for the function IACSManager::SetActive(IAuxCoordSysP auxCoordSys, ViewportR vp).
And I show, how I get some information from the activ acs:
static void viewinfo_showViewInfo(MSDialog *dbP) { dbP = mdlDialog_findByTypeAndId(RTYPE_DialogBox, DIALOGID_ViewInfo, NULL); DgnModelRefP model = mdlModelRef_getActive(); if (NULL == model) return; DgnFileP file = mdlModelRef_getDgnFile(model); if (NULL == file) return; ViewGroupCollectionCP vgc = &file->GetViewGroups(); ViewGroupP activeViewGroup = vgc->GetActiveP(); if (NULL == activeViewGroup) return; ViewInfoCR viewInfo = activeViewGroup->GetViewInfoR(viewInfoTestData.viewNo); WString sTemp, sInfo; sTemp = viewinfo_getStandardViewInfo(viewInfo); sInfo += sTemp; WChar pLabel[MAX_UNIT_LABEL_LENGTH]; const double uor = mdlModelRef_getUorPerMaster(model); mdlModelRef_getMasterUnitLabel(model, pLabel); sTemp.Sprintf(L"Auflösung (uor): %f per Abstand %s \n", uor, pLabel); sInfo += sTemp; IAuxCoordSysP acs = viewInfo.GetAuxCoordinateSystem(); sTemp.Sprintf(L"\nACS name: %s\n", acs->GetName()); sInfo += sTemp; bool isReadOnly = acs->GetIsReadOnly(); sTemp.Sprintf(L"ACS IsReadOnly: "); if (isReadOnly) { sTemp += L"Yes\n"; } else { sTemp += L"No\n"; } sInfo += sTemp; sTemp.Sprintf(L"ACS description: %s\n", acs->GetDescription()); sInfo += sTemp; sTemp.Sprintf(L"ACS typeName: %s\n", acs->GetTypeName()); sInfo += sTemp; DPoint3d acsOrigin; acs->GetOrigin(acsOrigin); sTemp.Sprintf(L"ACS origin: (%f, %f, %f) \n", acsOrigin.x / uor, acsOrigin.y / uor, acsOrigin.z / uor); sInfo += sTemp; RotMatrix acsRot; acs->GetRotation(acsRot); sTemp.Sprintf(L"ACS rotation (maxAbs): %f \n", acsRot.MaxAbs()); sInfo += sTemp; sTemp.Sprintf(L"ACS scale: %f \n", acs->GetScale()); sInfo += sTemp; sTemp.Sprintf(L"\nClose and reopen the \"ACS\" window, if changes were made!"); sInfo += sTemp; dbP->ItemSetValueByTypeAndId(RTYPE_MultilineText, MLTEXTID_ViewInfoDescription, sInfo.c_str()); }
If there are errors or enhancements, a reply would be nice. Have a nice Day.
Thanks Jon Summers!
Ole Gottwald said:If there are errorsRotMatrix acsRot; ... acs->SetRotation(acsRot);
RotMatrix acsRot; ... acs->SetRotation(acsRot);
An uninitialised rotation matrix is good for nothing. Prefer this...
RotMatrix acsRot; acsRot.InitIdentity(); ... acs->SetRotation(acsRot);
Is edited!
Without the function InitIdentity(), I'm not able to rotate view for example?