기본 콘텐츠로 건너뛰기

라벨이 MSTN V8인 게시물 표시

Polygon 해칭

주어진 정점으로 이루어진 Polygon을 해칭하는 예제입니다. inData는 "HATCHPLINE,0,0,0.1,0,0.1,0.1,0,0.1,0,0," 이런식으로 주어지면 됩니다. Private Sub drawHatchPline(ByVal inData As String) Dim m_oShapeElement As ShapeElement Dim m_Points() As Point3d Dim ptrn As CrossHatchPattern Dim vertices() As Point3d Dim tokens() As String Dim i As Integer, index As Integer index = 0 tokens = Split(inData, ",") ReDim Preserve m_Points(UBound(tokens) / 2) For i = 1 To UBound(tokens) m_Points(index) = Point3dFromXY(Val(tokens(i)), Val(tokens(i + 1))) i = i + 1 index = index + 1 Next Set m_oShapeElement = CreateShapeElement1(msv8Element, m_Points, msdFillModeNotFilled) ActiveModelReference.AddElement m_oShapeElement ' Use a CrossHatchPattern object to set up the parameters for ' the hatching operation. Set ptrn = CreateCrossHatchPattern(0.01, 0.01, Pi / 4, -Pi / 4) ver...

선택한 Text의 정보 출력

선택한 Text의 정보를 출력하는 예제입니다. Sub DisplaySelTextElement() Dim cim As CadInputMessage Dim oEnumerator As ElementEnumerator If Not ActiveModelReference.AnyElementsSelected Then ShowError "The macro requires a selection set" Exit Sub End If Set oEnumerator = ActiveModelReference.GetSelectedElements Do While oEnumerator.MoveNext Dim oElement As Element Set oElement = oEnumerator.Current If oElement.Type = msdElementTypeText Then ShowStatus oElement.AsTextElement.Text End If Loop End Sub

MSTN XM VBA - Lession4(요소 탐색하기)

아래 예제는 현재 열려 있는 모델의 요소에 접근하여 Range를 구하는 매크로 입니다. Sub EnumElements() Dim oScanEnumerator As ElementEnumerator Dim oElement As Element Set oScanEnumerator = ActiveModelReference.Scan Do While oScanEnumerator.MoveNext Set oElement = oScanEnumerator.Current If oElement.IsGraphical Then ShowStatus "Low = " & oElement.Range.Low.X & "," & oElement.Range.Low.Y ShowStatus "High= " & oElement.Range.High.X & "," & oElement.Range.High.Y End If Loop End Sub

mdlDim_getActualValues 오류

Dimension의 텍스트를 읽을때 텍스트가 자동으로 계산되어 표시되는 경우는 mdlText_extract 함수를 통하여 읽었을때 *로 읽힙니다. 이럴때 mdlDim_getActualValues 함수를 통하여 실제 값을 구할 수 있습니다. 하지만 이 함수가 완전하지 않은지 가끔씩 에러가 발생합니다. 원인과 해결 방법을 알고 계신 분은 좀 알려 주세요... double pdValues[256] = {0,}; f (SUCCESS == mdlDim_getActualValues(&(element->el) , pdValues)) { m_sTextString.Format (_T("%.4f") , (pdValues[0] / uor)); }

XData 쓰기 예제

xdata 쓰기 예제입니다. if (mdlElmdscr_read(&pDescr, filePosP , modelRef , FALSE , NULL) != 0) { ElementId regAppID; static MSWChar *s_applicationName = L"Rev.Pro"; if (SUCCESS == mdlRegApp_idFromName (&regAppID, s_applicationName , mdlModelRef_getDgnFile(MASTERFILE), TRUE)) { XDataValueUnion data; int dataType; int groupCode; UInt32 dataSize; UInt32 index = NULL; if(pDescr->h.isHeader && pDescr->h.firstElem) { for(MSElementDescrP ptr = pDescr->h.firstElem;NULL != ptr;ptr = ptr->h.next) { UInt32 color = 0; mdlElement_getSymbology(&color, NULL , NULL , &(ptr->el)); //기존 데이타 있는지 체크.. if (SUCCESS != mdlLinkage_getXDataGroupCode (&data, &dataType, &dataSize, &groupCode, &(ptr->el) , &index)) { const int...

[MDL] ProgressBar 표현

어떤 다소 시간이 걸리는 작업을 할때 사용자들을 멍~하니 기다리게 하는 것보다 ProgressBar를 표시하는 것이 효과적입니다. 예제) 열린 파일에서 현재 읽고 있는 요소대한 진행 상태를 표시하는 방법에 대해 알아보도록 하겠습니다.(즉 현재 몇번째 요소를 읽고 있는지 나타내는...) 1. 화면에 표시할 다이얼로그 리소스 준비 2. 다이얼로그를 생성할 스레드 생성 작업 스레드에서 다이얼로그를 생성하도록 합니다. 여기서 하고 싶은 말 : mdlXXX류의 함수는 작업 스레드에서 제대로 작동하지 않을수 있으니... 주 스레드에서 호출해야 한다는 것입니다. /****************************************************************************** @author humkyung @date 2011-08-22 @class @function StatusThreadEntry @return UINT @param LPVOID pVoid @brief ******************************************************************************/ UINT StatusThreadEntry(LPVOID pVoid) { CWorkStatusDlg* pDlg = (CWorkStatusDlg*)(pVoid); if(pDlg) { InterlockedExchange((LONG*)(&(pDlg->m_bThreadRunning)) , TRUE); pDlg->DoModal(); } return ERROR_SUCCESS; } extern "C" __declspec(dllexport) int __stdcall RevMISC(const CString &INI_FILE_PATH) ...

Element 탐색하기 - 두 번째

앞서 Element를 탐색하는 방법을 알아봤는데 이번에는 또 다른 방법을 알아 보도록 하겠습니다. 이번에 알아볼 방법은 Callback함수를 이용하는 방법입니다. Callback함수를 등록시켜 놓으면 scan시 Element를 찾을때 마다 Callback함수를 호출합니다. 아래의 코드를 참조하세요 /*---------------------------------------------------------------------------------**//** author BentleySystems 03/04 +---------------+---------------+---------------+---------------+---------------+------*/ int CNeutralDataFile::ScanCallback ( MSElementDescr* pEd, void* pInfo, ScanCriteria* pScanCriteria ) { UNUSED_ALWAYS(pScanCriteria); CNeutralDataFile* pNeutralDataFile = (CNeutralDataFile*)(pInfo); pNeutralDataFile->WriteElementDescr(pEd , 0L); return SUCCESS; } /* @brief write element to file @author @date 2011.07.04 @param CStdioFile& */ void CNeutralDataFile::WriteToFile(/*CStdioFile* pStdioFile*/) { { ScanCriteria *scP = mdlScanCriteria_create (); /...

Sheet 정보 추출하기

아래 코드를 참조하시기 바랍니다. DgnIndexItemP indexItem = NULL; DgnIndexIteratorP pIterator = mdlModelIterator_create(mdlModelRef_getDgnFile (mdlModelRef_getActive())); while(NULL != (indexItem = mdlModelIterator_getNext (pIterator))) { ModelID modelId = mdlModelItem_getModelID (indexItem); DgnModelRefP pModel = NULL; mdlModelRef_createWorking (&pModel,mdlModelRef_getDgnFile(mdlModelRef_getActive ()),modelId,TRUE,TRUE); if(mdlModelRef_isSheet (pModel)) { CDgnSheet DgnSheet(pModel); DgnSheet.GetSheetDefInfo(); //! sheet 정보를 text 파일로 출력(테스트용) DgnSheet.WriteToFile(_T("C:\\TEST.txt")); } mdlModelRef_freeWorking (pModel); } /* @brief get sheet definition @author humkyung @date 2011.07.04 **/ int CDgnSheet::GetSheetDefInfo() { if (mdlModelRef_isSheet (m_pModelRef)) { SheetDef *pSheetDef = NULL; //! sheet definition 생성(mdlSheetDef_new 함수를 통해서만 sheet definition을 생성할 수 ...

SmartSolid에서 Surface 추출

아래의 코드를 이용해서 SmartSolid에서 Surface를 추출할수 있습니다. if(mdlKISolid_isSmartElement(pElmDescr , MASTERFILE , filePos)) { MSElementDescrP destP = NULL; mdlKISolid_beginCurrTrans(MASTERFILE); // SmartSolid를 suface 리스트를 추출 // destP에 추출한 surface 리스트가 담겨 있습니다. mdlKISolid_getSurfaceElements(&destP , pElmDescr , MASTERFILE , NULL); mdlKISolid_endCurrTrans(); WriteElementDescr(oFile , pDgnModelRef , destP , filePos , dUOR , DGNType); mdlElmdscr_freeAll (&destP); }

Element 기준으로 View를 Fit하기

아래 예제 코드를 참고 하시기 바랍니다. ret = mdlElement_read (&mseFeat, MASTERFILE, filePosP); if (SUCCESS == ret) { if (SUCCESS == mdlElement_extractRange (&dvVec, &mseFeat)) { memset (&options, 0, sizeof (FitViewOptions)); if (SUCCESS == mdlView_fitViewToRange (&dvVec.org, &dvVec.end, &options, 0)) {

error C3861: 'toolSubsystem_fwrite': identifier not found

V8i용 프로그램을 개발할때 파일을 읽기 위해 fstream을 인클루드했을때 아래와 같은 에러를 뱉어 내었습니다. 아마도 mdl 관련 헤더 파일에서 이 부분을 재정의를 한 것 같습니다.(왜 그렇게 했는지는 이해가 안 가네요...) 단지 아래와 같이 fstream을 인클루드만 했을뿐인데 말이죠... #include <fstream> #include <vector> using namespace std; // CDockableDialog dialog IMPLEMENT_DYNAMIC(CDockableDialog, CBNETDockableDialog)

Dockingbar 만들기 V8 / MSTN/MDL/VBA

Arx에서도 MDL에서도 Dockingbar는 인기가 많은 모양입니다. V8i에서 사용가능한 Dockingbar를 만들어 달라고 해서 한번 만들어 봤습니다. 여기서 가장 핵심은 Microstation SDK의 CBNETDockableDialog 클래스를 사용한다는 겁니다. 이 클래스를 사용하면 손쉽게 도킹바를 만들수 있습니다. 우선 결과부터 먼저 보시죠(실제 코딩은 거의 없기 때문에...) 전체적인 흐름은 앞서 설명한 것과 동일하고요, 도킹바로 사용할 다이얼로그를 하나 만들고 거기서 클래스 하나를 생성합니다. #pragma once #include <mfc/CBNETDockableDialog.h> // CDockableDialog dialog class CDockableDialog : public CBNETDockableDialog { DECLARE_DYNAMIC(CDockableDialog) public: CDockableDialog(TCHAR *pTitle = NULL); // standard constructor virtual ~CDockableDialog(); // Dialog Data enum { IDD = IDD_DOCKABLE }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() }; 그리고 MdlMain 함수에서 도킹바를 생성합니다. [-] Collapse /*******************************************************************************************/ //Function:extern "C" DLLEXPORT int MdlMain //Desc:Entry point of th...

jsm 파일 만들기의 문제점 V8 / MSTN/MDL/VBA

Interference Manager를 통해서 jsm 파일을 만들때, dgn item에 들어 있는 내용은 jsm 파일의 property에 넣어 줄수 있습니다. 하지만 dgn item에 없는 사용자 property를 넣어주기 위해서 간략한 MDL App.를 만들었는데 이것의 문제점은 실제로 interference가 발생하지 않으면 MDL App의 함수가 호출되지 않는다는 것입니다.(이 함수에서 사용자 property의 값을 넣어주게 됩니다.) 그래서 테스트를 위해 임의로 CELL을 Support Model과 interference가 발생하게 넣어주고 interference mananger를 통해서 MDL App.를 호출하였는데, 여기서 또한 문제가 발생했습니다. 넣어준 CELL의 property에는 값을 넣어줄 수가 있었는데 정작 필요한 support model의 property에는 값을 넣어 줄수가 없는 것이었습니다. 이 부분을 어떻게 다루어야 하는지 모르겠습니다.(Support Model의 property 값을 넣도록 하는 것) 2011.02.23 Application Setting에서 Design Series 체크 버튼을 끄고 하면 Support Model의 Property에 값을 넣을수는 있는데, 가장 상위의 Cell에만 들어가는 문제가 또 있습니다. Assembly로 만든 Support는 각 Component가 Nested Cell 형식으로 존재하게 되는데, 결과적으로 Nested Cell의 Property에 값을 넣어 줄수가 없는 것입니다. 2011.02.24 Navigator COM API로 jsm 파일 안에 있는 propery를 찾고 , 값을 변경 그리고 저장할수 있다고 합니다. 하지만 누가 프로그램을 짜서 이렇게 할려고 할까요? Navigator가 시장에서 많이 사용하고 있는 것도 아니고 또한 공짜로 배포하고 있는데 말이죠...

jsm 파일 만들기

Bentley 제품군에서 Navigator라는 제품이 있습니다. 이름에서도 풍기듯이 모델링하는 툴이 아니라 뷰어입니다. Navigator가 jsm 파일을 읽을 수 있는데 이 jsm 파일은 Dgn 파일을 변환시킨 것입니다. 왜 굳이 시간을 들여가면서 Dgn 파일을 변환하여 jsm 파일을 만든 후에 이것을 Navigator로 볼까? 하는 의구심이 들기도 했습니다만... 이렇게 하는 이유?가 있었습니다. 보고자 하는 속성들을 jsm 파일을 만들때 넣어 줄수 있다는 것입니다. 즉 보기 쉽게 포맷된 형식으로 속성을 넣어 볼수 있다는 것입니다. 이 포맷된 형식은 JSpace Class Editor라는 툴을 이용하여 정의할수 있습니다. 사실 JSpace Class Editor는 약간 오래된 프로그램인데, KEPCO E&C에서 현재 사용하고 있습니다. 예를 들면 위의 형식대로 Navigator에서 볼수 있다는 것입니다. 실제 jsm 파일 생성은 Interference manager에서 합니다. Grouping Class 버튼을 눌러 JSpace Class Editor에서 생성한 Class Library를 선택합니다. 최종적으로 'Extract' 버튼을 누르면 jsm 파일이 생성됩니다. <Bentley Navigator 화면>

Extracting smart solid element

MSElementDescrP bodyToElements ( KIBODY* pBody, // => MSElementP pTemplate, // => can be NULL int nIsoLines // => ) { MSElementDescrP pNewEd = NULL; if (NULL == pBody) return NULL; mdlKISolid_beginCurrTrans (ACTIVEMODEL); mdlKISolid_bodyToElements (&pNewEd, pBody, TRUE, nIsoLines, pTemplate, ACTIVEMODEL); mdlKISolid_endCurrTrans (); return pNewEd; } ;2011.07.04 kisolid.dll를 library에 추가해야 합니다.

XM MDL Programming - #9(메뉴 생성하기)

dgnlib 이라는 파일을 가지고 툴바와 메뉴를 생성할 수 있습니다. 우선 Project와 User를 선택하여 해당 dgnlib 파일을 엽니다. Workspace --> Customize 메뉴로 갑니다. 오른쪽 부분에서 마우스 오른쪽 클릭을 하여 New Menu 와 New Menu Item 을 통하여 메뉴를 생성합니다. 메뉴를 생성했다면 메뉴를 선택했을 때 실행되는 루틴을 설정하는게 꼭 필요한데요, 메뉴의 Properties 항목 중에서 Key-in 항목에서 실행하는 명령을 입력하면됩니다. 메뉴와 실행되는 명령이 서로 부합되지는 않지만 뭐~~ dgnlib 파일을 저장하고 나서 빠져 나갑니다. 이제 dgn 파일을 오픈해 보면 우리가 방금 만든 메뉴가 기존의 메뉴에 추가되어 있는 것을 볼 수 있습니다. 앞서 우리가 만든 dgnlib 파일은 general Project 그리고 example User 일 때만 적용됩니다.

XM MDL Programming - #8(Visual Studio Project 생성하기)

순서가 뒤바뀐 감이 없지 않지만, 이번에는 Visual Stuido Project를 생성하여 설정을 하는 방법에 대해서 알아보도록 합시다. 일단은 MFC DLL 프로젝트를 하나 생성합니다. 기본값으로 그냥 생성하시면 됩니다. 그리고 SDK가 설치되어 있는 폴더를 설정합니다. 다음에는 Preprocessor를 설정합니다. 아래 그림과 같이 winNT를 추가합니다. 그리고 디버깅 모드일때는 _DEBUG를 _DEBUG_BUILD로 변경해주세요. 디버깅 모드일 때 코드 생성의 런타임 라이브러리를 아래와 같이 (/MDd)로 변경해주세요. Compiled Header를 Create Precompiled Header (/Yc) 로 설정해 주세요. Linker에서 Additional Library Directory를 설정합니다. 그리고 추가 Library를 등록합니다. 기본적인 Library항목은 아래와 같습니다. toolsubs.lib dgnfileio.lib ditemlib.lib mdlbltin.lib nativewindow.lib nativewinmfc.lib mdllib.lib UI를 만들지 않는다면 nativewindow.lib nativewinmfc.lib 이를 링크해 줄 필요가 없습니다. 이렇게 하면 기본적인 프로젝트 설정이 끝납니다.~~

XM MDL Programming - #5(Element 생성하기)

이번에는 간단히 예제로 Line과 Text를 생성하는 방법에 대해 알아보도록 합시다. 다른 Element들에 대해서는 생성하는 함수만 알면 아래의 루틴대로 하면 아무 어려움 없이 원하는 Element들을 생성할수 있습니다. 루틴이라고 해봤자 생성하는 함수로 원하는 Element를 생성한 후에 Property를 설정하고 add하는 것 밖에 없습니다. 우선 간단한 다이얼로를 만든 뒤에 생성할 Element의 Type을 설정하는 ComboBox를 추가합니다. 그리고 Place 버튼을 누르면 Element를 생성하는 것으로 하죠. 자 그럼 Place 버튼의 Callback 함수를 보도록 하죠. void CModelessDlg::OnBnClickedBtnPlace() { CMStationDialog::UpdateData(TRUE); startElementPlacement(this); } 아래 startElementPlacement 함수를 호출합니다. void startElementPlacement(CModelessDlg* pDlg) { g_pDlg = pDlg; CString csElement; int nIndex = g_pDlg->m_cbCtrlElemType.GetCurSel(); if(nIndex != -1) { g_pDlg->m_cbCtrlElemType.GetLBText(nIndex,csElement); if(csElement.CompareNoCase("Line") == 0) { startLinePlacement(); } else if(csElement.CompareNoCase("Text") == 0) { mdlState_setFunction (STATE_DATAPOINT, placeText); ...

Element 탐색하기

이번에는 dgn 파일에 있는 element들을 찾는 방법을 알아보도록 합시다. 먼저 간단한 코드를 먼저 보시죠. int ScanFile(UShort* typeMask , constintmaskSize) { intstatus = 0; intnElemCnt = 0; intnElemType; ULong elemAddr[50]; ScanCriteria* pScanCrit = NULL; UShort usTypeMask[8]; MSElement element; // Initialize the scan criteria pScanCrit = mdlScanCriteria_create(); mdlScanCriteria_setReturnType(pScanCrit, MSSCANCRIT_RETURN_FILEPOS, FALSE, FALSE); memset(usTypeMask, 0, sizeof(usTypeMask)); mdlScanCriteria_setElementTypeTest(pScanCrit , typeMask , maskSize); mdlScanCriteria_setModel (pScanCrit,mdlModelRef_getActive()); mdlScanCriteria_setElementCategory (pScanCrit,ELEMENT_CATEGORY_GRAPHICS); do { intscanWords = sizeof(elemAddr) / sizeof(short); status = mdlScanCriteria_scan(pScanCrit, elemAddr, &scanWords, NULL); if( status == BAD_FILE || status == BAD_ELEMENT ) break; intnumAddr = scanWords / sizeof(short); for(int i=...

XM MDL Programming - #3(Command 사용하기)

이번에는 Command를 사용하는 방법에 대해서 알아보도록 하죠. 일단 먼저 MSTN의 리소스 파일을 이용하여 Command 구조를 선언합니다. 이것을 컴파일하면 .ma 파일이 생성됩니다. CT_BASIC이 최상위 Command Table 이름이고, CT_DELETE라는 하위 Command Table을 필요(REQ)로 합니다. CT_DELETE라는 Table은 CT_BASICAPP에서 상속(INHERIT)을 받고 더 이상의 하위 Command Table은 필요로 하지 않습니다. .mke 파일을 잠깐 살펴보면... # Create needed output directories if they don't exist $(rscOutDir)$(tstdir) : $(rscOutDir)$(tstdir) $(maOutDir)$(tstdir) : $(maOutDir)$(tstdir) rscCompIncs + -i$(hdrOutDir) -i$(baseDir)inc/ appRscs = $(rscOutDir)$(appName).rsc $(incDir)$(appName)Cmd.h : $(rsrcInc)$(appName)Cmd.r $(rscOutDir)$(appName)Cmd.rsc : $(rsrcInc)$(appName)Cmd.r $(rscOutDir)$(appName).rsc : $(rsrcInc)$(appName).r rscLinkObjs = $(rscOutDir)$(appName).rsc\ $(rscOutDir)$(appName)Cmd.rsc 여기서 배경이 노란줄을 주의해서 살펴볼 필요가 있습니다. Command를 정보를 가지고 있는 리소스 파일에서 *.h 파일을 생성시키는 부분입니다. 이 *.h 파일은 아래에서 사용할 Command Number를 가지고 있습니다. #define CMD_MYDELETE 0x01000000 /* MANIPULATION */ #defin...