Get and Set ACS

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

  • 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 can ask someone to diagnose it.

    I saw the "mdlACS_"-Functions,

    Those are probably wrappers around the IAuxCoordSys class. 

    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.

  • only the output of "ACS origin"
    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);
    
    The output of "scale" was "0"
    sTemp.Sprintf(L"ACS scale: %.2lf", acs->GetScale());

    Formatting

    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.

     
    Regards, Jon Summers
    LA Solutions

    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.

    Best regards

  • Maybe this should be changed there, too

    Yes: there's nothing worse than an example that doesn't work!  please note.

     
    Regards, Jon Summers
    LA Solutions

  • 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!

  • 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).

     
    Regards, Jon Summers
    LA Solutions

  • 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!

    Answer Verified By: Ole Gottwald 

  • If there are errors
    RotMatrix acsRot;
    ...
    acs->SetRotation(acsRot);

    An uninitialised rotation matrix is good for nothing.  Prefer this...

    RotMatrix acsRot;
    acsRot.InitIdentity();
    ...
    acs->SetRotation(acsRot);

     
    Regards, Jon Summers
    LA Solutions

  • Is edited!

    Without the function InitIdentity(), I'm not able to rotate view for example?