1. SpPlugin.dll можно подключить к другой программе и пользоваться тем сервисом что предоставляет SpPlugin.dll (массивы точек, матрицы, геометрические преобразования......)
2. Если использовать SAPFIR.tlb, то есть варианты.
2.1 если .NET Framework то подключаете SAPFIR.tlb в свойствах проекта как ссылку.
Для доступа к точкам нужен массив SafeArray или JScriptArray, которые нужно подставить в VARIANT. Такая реализация для работы с массивами вариантов нужна для совместимости со скриптовыми языками (JScript, VBScript,...).
Вот пример как это можно организовать:
| Код |
|---|
ref class CP3{
public:
double x, y, z;
};
SapfirLib::AutoModel ^pObj = (SapfirLib::AutoModel ^)pSt->GetModelByIndex(i);
if (pObj)
{
long type = pObj->TypeModel; // получить тип модели
if (type==10) // Если стена TM_WALL
{
pModel->Select = 1; // выделим (подсветим) стену в САПФИРЕ
SapfirLib::AutoPolyLine ^pLine = (SapfirLib::AutoPolyLine ^)pObj->GetAxisLine();
if (pLine)
{
Object^ ObjPnt = gcnew array<Ob ject ^>(0); // Создаем пустой SafeArray массив(такая реализация для работы с массивами вариантов нужна для совместимости с скриптовыми языками)
pLine->GetPoints(ObjPnt); // получаем массив точек, где Points[0]=x1,Points[1]=y1,Points[2]=z1, Points[3]=x2,Points[4]=y2,Points[5]=z2,.....
Array ^ArrPnt = (System::Array^)ObjPnt; // приводим к массиву
long len = ArrPnt->Length; // количество координат в массиве
long cnt = len / 3; // количество точек
array<CP3 ^> ^ Points = gcnew array<CP3 ^>(cnt); // распределяем массив для точек
for (long j = 0; j < cnt; j ++ )
{
CP3 ^pnt = gcnew CP3;
pnt->x = (double)ArrPnt->GetValue(j*3);
pnt->y = (double)ArrPnt->GetValue(j * 3 + 1);
pnt->z = (double)ArrPnt->GetValue(j * 3 + 2);
Points[j] = pnt; // заносим точку в массив
}
}
break;
}
}
|
2.2 Если через импорт библиотеки типов, то пример ниже
| Код |
|---|
#include <atlbase.h>
#include <atlsafe.h>
#import "...\sapfir.tlb" // auto_search auto_rename
// константы см. const_model.jsh
#define IMF_3D 0x001 // 3D модель
#define TM3_LINE 1 // тип сегмента: отрезок
#define TM3_ARC 2 // тип сегмента: дуга
#define TM3_BEZIER 3 // тип сегмента: Безье
#define TM_WALL 10 // тип объекта стена
#define UPDATE_MODELS 0x1000 // перерисовать модель документа
//.....
void OnTestSapfir()
{
HRESULT hr = CoInitialize(NULL);
using namespace SapfirLib;
IApplication *SapfirApp = NULL;
CLSID ClassId;
hr = CLSIDFromProgID(L"Sapfir.Application", &ClassId);
if (FAILED(hr))
return ;
hr = CoCreateInstance(ClassId, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER, __uuidof(IApplication), reinterpret_cast<void**>(&SapfirApp));
if (FAILED(hr))
return;
if (SapfirApp)
{
// в версиях 2016 и 2017 САПФИР запускается без окна
SapfirApp->Visible = true; // так можно показать окно САПФИРА
ISapfirDocPtr pDоc = SapfirApp->GetActiveDoc(); // берем активный документ
if (pDоc) // если документ есть
{
IAutoStoreyPtr pSt = pDоc->GetActiveStorey(); // берем активный этаж документа
if (pSt) // если есть активный(текущий) этаж
{
long cnt = pSt->CountModel; // количество объектов на этаже
for (long i = 0; i < cnt; i++)
{
IAutoModelPtr pMod = pSt->GetModelByIndex(i); // берем очередной объект
if (pMod)
{
if (pMod->TypeModel == TM_WALL) // если это стена
{
IAutoPolyLinePtr pLn = pMod->GetAxisLine(); // берем полилинию контура
if (pLn)
{
{ //=================> Получение всех точек осевой стены
VARIANT vPntArr;
//--> первый способ
SAFEARRAYBOUND sab;
sab.lLbound = 0; sab.cElements = 0;
vPntArr.parray = SafeArrayCreate(VT_VARIANT, 1, &sab);
//<--
//--> второй способ
// CComSafeArray<VARIANT> arr(1);
// vPntArr.parray = arr;
//<--
vPntArr.vt = VT_ARRAY | VT_VARIANT; //!!! Нужно объявить как массив вариантов. Так нужно для всех массивов.
pLn->GetPoints(&vPntArr); // получаем точки
if (SAFEARRAY* saData = vPntArr.parray)
{
VARIANT HUGEP *pdFreq;
HRESULT hr = SafeArrayAccessData(saData, (void HUGEP* FAR*)&pdFreq); // получаем указатель на массив вариантов
long num_coord = saData->cbElements;
double pnt;
for (long ic = 0; ic < num_coord; ic++)
pnt = pdFreq[ic].dblVal;
}
}//<=====================
{ //=====================> пройтись по сегментам полилинии
long cnt_l = pLn->GetCountLine(); // количество сегментов в полилинии
for (long is = 0; is < cnt_l; is++)
{
IAutoLinePtr pSeg = pLn->GetLine(is);
if (pSeg)
{
long typeSeg = pSeg->GetTypeModel();
if (typeSeg == TM3_LINE) // отрезок
{
CComSafeArray<VARIANT> arr(1);
VARIANT vPntArr;
vPntArr.parray = arr;
vPntArr.vt = VT_ARRAY | VT_VARIANT; // массив вариантов
pSeg->GetPoints(&vPntArr); // получаем точки
}
}
}
}//<=======================
{ //======================> заменим точки осевой линии стены
CComSafeArray<VARIANT> arr(6);
double arrCood[] = { 0.05, 0.1, 0.0, 3.45, 1.2, 0.0 }; // координаты в метрах
for (long ic = 0; ic < 6; ic++)
arr[ic] = arrCood[ic];
VARIANT vPntArr;
vPntArr.vt = VT_ARRAY | VT_VARIANT; // массив вариантов
vPntArr.parray = arr;
pLn->SetPoints(vPntArr); // заносим новые точки (стена об этом ничего не знает!!!)
pMod->RegenModel(); // Заставим стену перестроить модель по новой осевой
} //<=====================
}
pDоc->DrawModel(UPDATE_MODELS); // обновим и перерисуем модель модель документа
}
}
}
}
}
}
} |