Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

1366 lines
32 KiB
C++

#include "StdAfx.h"
#include <string>
#include <set>
#include "parseFamilyForRevit.h"
#include "CoreTools.h"
#include "ktcadutilityex.h"
#include "_cgal.h"
#include "shJson.h"
#include "AecDbEwEquipment.h"
using namespace SHJson;
namespace
{
int initVersion() { return -1; }
static int g_nJsonVersion = initVersion();
static double g_dUnitRate;
long getFileSize(FILE *fp)
{
if (!fp) return 0L;
fseek(fp, 0L, SEEK_END);
long fSize = ftell(fp);
fseek(fp, 0L, 0L);
return fSize;
}
bool isCounterclockwise(const AcGePoint3d &pts
, const AcGePoint3d &ptm
, const AcGePoint3d &pte
, const AcGeVector3d &normal)
{
AcGeVector3d vtSM(ptm - pts);
AcGeVector3d vtME(pte - ptm);
if (vtSM.crossProduct(vtME).isCodirectionalTo(normal))
return true;
else
return false;
}
// 把pReg移动到与pCurve第一点相同的平面,平面特征取自pReg
void convertRegion(AcDbRegion *pReg, AcDbCurve *pCurve)
{
// 第一点的切线
AcGeVector3d vtTangle;
AcGePoint3d pts(AcGePoint3d::kOrigin);
pCurve->getStartPoint(pts);
pCurve->getFirstDeriv(pts, vtTangle);
vtTangle.normalize();
AcGePlane pathPlan(pts, vtTangle);
AcGePoint3d pt1;
AcGeVector3d x1, y1;
pathPlan.getCoordSystem(pt1, x1, y1);
AcGePlane regiPlan;
pReg->getPlane(regiPlan);
AcGePoint3d pt2;
AcGeVector3d x2, y2;
regiPlan.getCoordSystem(pt2, x2, y2);
AcGeMatrix3d mat;
mat.setToAlignCoordSys(pt1.orthoProject(regiPlan), x2, y2, x2.crossProduct(y2)
, pt1, x1, y1, x1.crossProduct(y1));
pReg->transformBy(mat);
}
struct RegionGeom
{
RegionGeom(AcDbRegion* pReg)
: m_ptCen(AcGePoint3d::kOrigin)
, m_dArea(.0)
, m_bVaild(false)
, m_bVoid(false)
, m_pSelf(pReg)
, m_pMotherShape(NULL)
{}
// 比自己大,且包含自己的截面
RegionGeom *m_pMotherShape;
// 形心
AcGePoint3d m_ptCen;
// 面积
double m_dArea;
//
AcDbRegion *m_pSelf;
// 是否有效
bool m_bVaild;
// 是否空心
bool m_bVoid;
// 排序用
static bool cmp(const RegionGeom *p1, const RegionGeom *p2)
{
return p1->m_dArea > p2->m_dArea;
}
};
RegionGeom* getRegionGeom(AcDbRegion *pReg)
{
RegionGeom *pRg(new RegionGeom(pReg));
if (!pReg) return pRg;
AcGePlane pln;
if (CoreTools::getRegionInfo(pReg, pRg->m_ptCen, pRg->m_dArea, pln))
pRg->m_bVaild = true;
return pRg;
}
bool regionInRegion(AcDbRegion *pRegSml, AcDbRegion *pRegBig)
{
if (!pRegSml || !pRegBig) return false;
AcGePlane plnSml, plnBig;
AcGePoint3d ptSml, ptBig;
double dSml(.0), dBig(.0);
if (!CoreTools::getRegionInfo(pRegSml, ptSml, dSml, plnSml)) return false;
if (!CoreTools::getRegionInfo(pRegBig, ptBig, dBig, plnBig)) return false;
// 不共面
if (!plnSml.isCoplanarTo(plnBig)) return false;
Geometry::Bounded_side bs = (Geometry::Bounded_side)CoreTools::ptInRegion(ptSml.convert2d(plnBig), pRegBig);
return bs == Geometry::eInside;
}
void getMotherRegion(RegionGeom &self, const std::vector<RegionGeom*> &rgs)
{
std::vector<RegionGeom*>::iterator it;
std::vector<RegionGeom*> _rgs(rgs);
self.m_pMotherShape = NULL;
for (it = _rgs.begin(); it != _rgs.end();)
{
RegionGeom &rg(**it);
// 去掉自己
if (self.m_pSelf == rg.m_pSelf)
{
_rgs.erase(it);
it = _rgs.begin();
continue;
}
// 比self面积小的,都不要
if (UPEQUAL(self.m_dArea, rg.m_dArea))
{
_rgs.erase(it);
it = _rgs.begin();
continue;
}
// self 不在其中的,不要
if (!regionInRegion(self.m_pSelf, rg.m_pSelf))
{
_rgs.erase(it);
it = _rgs.begin();
continue;
}
if (self.m_pMotherShape)
{
if (self.m_pMotherShape->m_dArea > rg.m_dArea)
self.m_pMotherShape = &rg;
}
else
self.m_pMotherShape = &rg;
_rgs.erase(it);
it = _rgs.begin();
}
return;
}
// 分析截面关系
void analyRegions(AcDbVoidPtrArray &regs, std::vector<RegionGeom*> &rgs, bool &bCombin)
{
// 首先 regs 内的region的轮廓不会相交,只会覆盖
// 所以只判断其形心是否在另一个region内就可判断是否覆盖
// 构建 RegionGeom 结构
for (int i(0); i < regs.length(); ++i)
{
RegionGeom *p = getRegionGeom((AcDbRegion*)regs[i]);
if (p->m_bVaild)
rgs.push_back(p);
}
// 分析出位置关系
for (size_t i(0); i < rgs.size(); ++i)
{
getMotherRegion(*rgs[i], rgs);
}
// 根据位置关系,得到 空心/实心 关系
std::vector<RegionGeom*> mothers;
for (size_t i(0); i < rgs.size(); ++i)
{
mothers.clear();
RegionGeom &rg(*rgs[i]);
RegionGeom *pMother(rg.m_pMotherShape);
while (pMother != NULL)
{
mothers.push_back(pMother);
pMother = pMother->m_pMotherShape;
}
int count((int)mothers.size());
if (count % 2)
rg.m_bVoid = true;
else
rg.m_bVoid = false;
}
if (regs.length() == 1)
bCombin = false;
else
{
for (size_t i(0); i < rgs.size(); ++i)
{
if (rgs[i]->m_bVoid)
{
bCombin = true;
break;
}
}
}
}
enum GeoType
{
// 2D
__kNone = 0,
kArc,
kLine,
kEllipse,
kCylindricalHelix,
kNurbSpline,
// 3D
kExtrusion,
kBlend,
kRevolution,
kSweep,
kSweptBlend,
// bim
kBims,
// 管嘴
kNozzle,
};
enum RVT_DOMAIN
{
kDomainUndefined = 0,
// 风管连接件
kDomainHvac = 1,
// 电气连接件
kDomainElectrical = 2,
// 管道连接件
kDomainPiping = 3,
// 电缆桥架连接件
kDomainCableTrayConduit = 4
};
enum RVT_ConnectorProfileType
{
kInvalid = -1,
// 圆
kRound = 0,
// 方
kRectangular = 1,
// 椭圆
kOval = 2
};
enum RVT_MEPSystemClassification
{
kUndefinedSystemClassification = 0,
kSupplyAir = 1,
kReturnAir = 2,
kExhaustAir = 3,
kOtherAir = 4,
kDataCircuit = 5,
kPowerCircuit = 6,
kSupplyHydronic = 7,
kReturnHydronic = 8,
kTelephone = 9,
kSecurity = 10,
kFireAlarm = 11,
kNurseCall = 12,
kControls = 13,
kCommunication = 14,
kCondensateDrain = 15,
kSanitary = 16,
kVent = 17,
kStorm = 18,
kDomesticHotWater = 19,
kDomesticColdWater = 20,
kRecirculation = 21,
kOtherPipe = 22,
kFireProtectWet = 23,
kFireProtectDry = 24,
kFireProtectPreaction = 25,
kFireProtectOther = 26,
kSwitchTopology = 27,
kFitting = 28,
kGlobal = 29,
kPowerBalanced = 30,
kPowerUnBalanced = 31,
kCableTrayConduit = 32
};
#define GET_TYPE(type1, type2) if (type1 == std::wstring(_T("SH")) + _T(#type2)) return k##type2
GeoType getGeoType(LPCTSTR psz)
{
if (!psz) return __kNone;
std::wstring t(psz);
GET_TYPE(t, Arc);
GET_TYPE(t, Line);
GET_TYPE(t, Ellipse);
GET_TYPE(t, CylindricalHelix);
GET_TYPE(t, NurbSpline);
GET_TYPE(t, Extrusion);
GET_TYPE(t, Blend);
GET_TYPE(t, Revolution);
GET_TYPE(t, Sweep);
GET_TYPE(t, SweptBlend);
GET_TYPE(t, Bims);
GET_TYPE(t, Nozzle);
return __kNone;
}
GeoType getGeoType(WCValue &v)
{
return getGeoType(v[_T("type")].GetString());
}
bool isGeo2D(const GeoType &type) { if (type == kNone) return false; return type < kExtrusion; }
bool isGeo3D(const GeoType &type) { if (type == kNone) return false; return type > kNurbSpline; }
template <typename T>
T parseXYZ(WCValue &v)
{
T t;
t.set(v[_T("X")].GetDouble(), v[_T("Y")].GetDouble(), v[_T("Z")].GetDouble());
return t;
}
AcGePoint3d parsePoint3D(WCValue &v)
{
if (g_nJsonVersion < 2) return AcGePoint3d::kOrigin;
return AcGePoint3d(v[_T("X")].GetDouble() * g_dUnitRate
, v[_T("Y")].GetDouble() * g_dUnitRate
, v[_T("Z")].GetDouble() * g_dUnitRate);
}
AcGeVector3d parseVector3D(WCValue &v)
{
if (g_nJsonVersion < 2) return AcGeVector3d::kIdentity;
double dX(v[_T("X")].GetDouble())
, dY(v[_T("Y")].GetDouble())
, dZ(v[_T("Z")].GetDouble());
AcGeVector3d vt(X, Y, Z);
if (vt.isUnitLength())
return vt;
else
return AcGeVector3d(dX * g_dUnitRate, dY * g_dUnitRate, dZ * g_dUnitRate);
}
void parsePoints(const CArr &ar, AcGePoint3dArray &pts)
{
for (size_t i = 0; i < ar.Size(); ++i)
{
WCValue &pt(ar[(rapidjson::SizeType)i]);
if (g_nJsonVersion < 2)
pts.append(parseXYZ<AcGePoint3d>(pt));
else
pts.append(parsePoint3D(pt));
}
}
void parseDoubles(const CArr &ar, AcGeDoubleArray &ds)
{
for (size_t i = 0; i < ar.Size(); ++i)
{
WCValue &d(ar[(rapidjson::SizeType)i]);
ds.append(d.GetDouble());
}
}
AcDb3dPolyline* pts2Polyline3D(AcGePoint3dArray &ar)
{
AcDb3dPolyline *p = new AcDb3dPolyline;
if (!p) return NULL;
for (int i = 0; i < ar.length(); ++i)
{
AcDb3dPolylineVertex *pV = new AcDb3dPolylineVertex(ar[(rapidjson::SizeType)i]);
p->appendVertex(pV);
}
return p;
}
AcGePlane parseSHPlane(WCValue &v)
{
AcGePoint3d pt;
AcGeVector3d normal;
AcGeVector3d xVec;
AcGeVector3d yVec;
if (g_nJsonVersion < 2)
{
pt = parseXYZ<AcGePoint3d>(v[_T("Origin")]);
normal = parseXYZ<AcGeVector3d>(v[_T("Normal")]);
xVec = parseXYZ<AcGeVector3d>(v[_T("XVec")]);
yVec = parseXYZ<AcGeVector3d>(v[_T("YVec")]);
}
else
{
pt = parsePoint3D(v[_T("Origin")]);
normal = parseVector3D(v[_T("Normal")]);
xVec = parseVector3D(v[_T("XVec")]);
yVec = parseVector3D(v[_T("YVec")]);
}
AcGePlane plan;
plan.set(pt, normal);
return plan;
}
AcDbEntity* parseSHArc(WCValue &v)
{
bool IsBound(v[_T("IsBound")].GetBool());
AcGePoint3d ptCenter;
AcGeVector3d vtNormal, vtYDir, vtXDir;
double dRadius;
if (g_nJsonVersion < 2)
{
ptCenter = parseXYZ<AcGePoint3d>(v[_T("Center")]);
vtNormal = parseXYZ<AcGeVector3d>(v[_T("Normal")]);
vtYDir = parseXYZ<AcGeVector3d>(v[_T("YDirection")]);
vtXDir = parseXYZ<AcGeVector3d>(v[_T("XDirection")]);
dRadius = v[_T("Radius")].GetDouble();
}
else
{
ptCenter = parsePoint3D(v[_T("Center")]);
vtNormal = parseVector3D(v[_T("Normal")]);
vtYDir = parseVector3D(v[_T("YDirection")]);
vtXDir = parseVector3D(v[_T("XDirection")]);
dRadius = v[_T("Radius")].GetDouble() * g_dUnitRate;
}
if (!IsBound)
{
return new AcDbCircle(ptCenter, vtNormal, dRadius);
}
else
{
double dSAngle(v[_T("startAngle")].GetDouble());
double dEAngle(v[_T("endAngle")].GetDouble());
AcGeMatrix3d mat;
vtXDir.normalize();
vtYDir.normalize();
vtNormal.normalize();
mat.setCoordSystem(ptCenter, vtXDir, vtYDir, vtNormal);
AcDbArc *pArc = new AcDbArc(ptCenter, AcGeVector3d::kZAxis, dRadius, dSAngle, dEAngle);
pArc->transformBy(mat);
AcGePoint3d ptC = pArc->center();
mat.setToIdentity();
mat.setTranslation(ptCenter - ptC);
pArc->transformBy(mat);
return pArc;
}
return NULL;
}
AcDbEntity* parseSHLine(WCValue &v)
{
bool IsBound(v[_T("IsBound")].GetBool());
AcGeVector3d vt;
AcGePoint3d pt, ptS, ptE;
if (g_nJsonVersion < 2)
{
vt = parseXYZ<AcGeVector3d>(v[_T("Direction")]);
pt = parseXYZ<AcGePoint3d>(v[_T("Origin")]);
ptS = parseXYZ<AcGePoint3d>(v[_T("start")]);
ptE = parseXYZ<AcGePoint3d>(v[_T("end")]);
}
else
{
vt = parseVector3D(v[_T("Direction")]);
pt = parsePoint3D(v[_T("Origin")]);
ptS = parsePoint3D(v[_T("start")]);
ptE = parsePoint3D(v[_T("end")]);
}
if (IsBound)
return new AcDbLine(ptS, ptE);
else
{
AcDbRay *pRay = new AcDbRay();
pRay->setUnitDir(vt);
pRay->setBasePoint(pt);
return pRay;
}
return NULL;
}
AcDbEntity* parseSHEllipse(WCValue &v)
{
bool IsBound(v[_T("IsBound")].GetBool());
AcGePoint3d ptCenter;
AcGeVector3d vtNormal, vtYDir, vtXDir;
if (g_nJsonVersion < 2)
{
ptCenter = parseXYZ<AcGePoint3d>(v[_T("Center")]);
vtNormal = parseXYZ<AcGeVector3d>(v[_T("Normal")]);
vtYDir = parseXYZ<AcGeVector3d>(v[_T("YDirection")]);
vtXDir = parseXYZ<AcGeVector3d>(v[_T("XDirection")]);
}
else
{
ptCenter = parsePoint3D(v[_T("Center")]);
vtNormal = parseVector3D(v[_T("Normal")]);
vtYDir = parseVector3D(v[_T("YDirection")]);
vtXDir = parseVector3D(v[_T("XDirection")]);
}
vtNormal.normalize();
vtYDir.normalize();
vtXDir.normalize();
double dRadiusX, dRadiusY;
if (g_nJsonVersion < 2)
{
dRadiusX = v[_T("RadiusX")].GetDouble();
dRadiusY = v[_T("RadiusY")].GetDouble();
}
else
{
dRadiusX = v[_T("RadiusX")].GetDouble() * g_dUnitRate;
dRadiusY = v[_T("RadiusY")].GetDouble() * g_dUnitRate;
}
if (!IsBound)
{
return new AcDbEllipse(ptCenter, vtNormal, vtXDir * dRadiusX, dRadiusY / dRadiusX);
}
else
{
double dSAngle(v[_T("startAngle")].GetDouble());
double dEAngle(v[_T("endAngle")].GetDouble());
return new AcDbEllipse(ptCenter, vtNormal, vtXDir * dRadiusX, dRadiusY / dRadiusX, dSAngle, dEAngle);
}
return NULL;
}
AcDbEntity* parseSHCylindricalHelix(WCValue &v)
{
AcGePoint3dArray pts;
parsePoints(v[_T("points")].GetArray(), pts);
return pts2Polyline3D(pts);
}
AcDbEntity* parseSHNurbSpline(WCValue &v)
{
int iDegree(v[_T("Degree")].GetInt());
bool isClosed(v[_T("isClosed")].GetBool())
, isRational(v[_T("isRational")].GetBool());
AcGePoint3dArray ctrlPts;
parsePoints(v[_T("CtrlPoints")].GetArray(), ctrlPts);
if (ctrlPts.isEmpty()) return NULL;
AcGeDoubleArray Knots, Weights;
parseDoubles(v[_T("Knots")].GetArray(), Knots);
if (Knots.isEmpty()) return NULL;
parseDoubles(v[_T("Weights")].GetArray(), Weights);
if (Weights.isEmpty()) return NULL;
return new AcDbSpline(iDegree, isRational, isClosed, false, ctrlPts, Knots, Weights);
}
void parseSHProfile(WCValue&, AcDbVoidPtrArray&, AcGePlane *pPlan = NULL);
AcDbEntity* parsePath(const CArr&);
void parseSHExtrusion(WCValue &v, std::vector<NewSolidBase*> &solids)
{
double startOffset, endOffset;
if (g_nJsonVersion < 2)
{
startOffset = v[_T("startOffset")].GetDouble();
endOffset = v[_T("endOffset")].GetDouble();
}
else
{
startOffset = v[_T("startOffset")].GetDouble() * g_dUnitRate;
endOffset = v[_T("endOffset")].GetDouble() * g_dUnitRate;
}
AcGePlane plan;
AcDbVoidPtrArray regs;
parseSHProfile(v[_T("curve")], regs, &plan);
if (regs.isEmpty())
return;
bool bCombin(false);
std::vector<RegionGeom*> rgs;
analyRegions(regs, rgs, bCombin);
AcGeVector3d vtNormal(plan.normal()), vt;
vtNormal.normalize();
AcGePoint3d pts, pte;
plan.get(pts, vt, vt);
pte = pts;
pts += vtNormal * startOffset;
pte += vtNormal * endOffset;
AcGeMatrix3d mat;
mat.setTranslation(vtNormal * startOffset);
bool bSolid(v[_T("isSolid")].GetBool());
if (!bCombin)
{
for (int i(0); i < regs.length(); ++i)
{
AcDbRegion *pReg((AcDbRegion*)regs[i]);
pReg->transformBy(mat);
AcGeVector3d vtReg;
pReg->getNormal(vtReg);
vtReg.normalize();
int iSingle(1);
if (!vtReg.isCodirectionalTo(pte - pts))
iSingle = -1;
solids.push_back(new NewExtrude(bSolid, pReg, iSingle * pts.distanceTo(pte)));
}
}
else
{
// 对 rgs 按面积从大到小排序
std::sort(rgs.begin(), rgs.end(), RegionGeom::cmp);
RevitCombination *pRc = new RevitCombination();
pRc->m_bSolid = bSolid;
pRc->m_bOrderDraw = true;
for (size_t i(0); i < rgs.size(); ++i)
{
RegionGeom &rg(*rgs[i]);
AcDbRegion *pReg(rg.m_pSelf);
pReg->transformBy(mat);
AcGeVector3d vtReg;
pReg->getNormal(vtReg);
vtReg.normalize();
int iSingle(1);
if (!vtReg.isCodirectionalTo(pte - pts))
iSingle = -1;
pRc->m_solids.push_back(new NewExtrude(!rg.m_bVoid, pReg, iSingle * pts.distanceTo(pte)));
}
solids.push_back(pRc);
}
deleteArrayVoidPtrs< AcDbRegion>(regs);
deleteContainerOfStd(rgs);
}
void parseSHBlend(WCValue &v, std::vector<NewSolidBase*> &solids)
{
bool isSolid = v[_T("isSolid")].GetBool();
AcGePlane topPlan, botPlan;
AcDbVoidPtrArray topRegs, bottomRegs;
AcDbRegion *top(NULL), *bottom(NULL);
parseSHProfile(v[_T("top")], topRegs, &topPlan);
parseSHProfile(v[_T("bottom")], bottomRegs, &botPlan);
if (topRegs.isEmpty()) return;
if (bottomRegs.isEmpty()) return;
double topOffset, bottomOffset;
if (g_nJsonVersion < 2)
{
topOffset = v[_T("topOffset")].GetDouble();
bottomOffset = v[_T("bottomOffset")].GetDouble();
}
else
{
topOffset = v[_T("topOffset")].GetDouble() * g_dUnitRate;
bottomOffset = v[_T("bottomOffset")].GetDouble() * g_dUnitRate;
}
AcGeMatrix3d topMat, botMat;
AcGeVector3d topVt(topPlan.normal()), botVt(botPlan.normal());
topVt.normalize();
botVt.normalize();
topVt *= topOffset;
botVt *= bottomOffset;
topMat.setTranslation(topVt);
botMat.setTranslation(botVt);
top = (AcDbRegion*)topRegs[0];
bottom = (AcDbRegion*)bottomRegs[0];
top->transformBy(topMat);
bottom->transformBy(botMat);
AcArray<AcDbRegion*> regs;
regs.append(top);
regs.append(bottom);
solids.push_back(new NewLoft(isSolid, regs, NULL));
deleteArrayVoidPtrs< AcDbRegion>(topRegs);
deleteArrayVoidPtrs< AcDbRegion>(bottomRegs);
}
void parseSHSweptBlend(WCValue &v, std::vector<NewSolidBase*> &solids)
{
bool isSolid = v[_T("isSolid")].GetBool();
AcDbVoidPtrArray topRegs, bottomRegs;
parseSHProfile(v[_T("top")], topRegs);
parseSHProfile(v[_T("bottom")], bottomRegs);
if (topRegs.isEmpty()) return;
if (bottomRegs.isEmpty()) return;
AcArray<AcDbRegion*> regs;
regs.append((AcDbRegion*)topRegs[0]);
regs.append((AcDbRegion*)bottomRegs[0]);
AcDbPolyline *pPath = (AcDbPolyline*)parsePath((v[_T("path")])[_T("path")].GetArray());
if (!pPath) return;
solids.push_back(new NewLoft(isSolid, regs, pPath));
DELETE_PTR(pPath);
deleteArrayVoidPtrs< AcDbRegion>(topRegs);
deleteArrayVoidPtrs< AcDbRegion>(bottomRegs);
}
void parseSHRevolution(WCValue &v, std::vector<NewSolidBase*> &solids)
{
bool isSolid = v[_T("isSolid")].GetBool();
AcGeVector3d vt;
AcGePoint3d pt;
if (g_nJsonVersion < 2)
{
vt = parseXYZ<AcGeVector3d>(v[_T("direction")]);
pt = parseXYZ<AcGePoint3d>(v[_T("point")]);
}
else
{
vt = parseVector3D(v[_T("direction")]);
pt = parsePoint3D(v[_T("point")]);
}
double dSAngle(v[_T("startAngle")].GetDouble());
double dEAngle(v[_T("endAngle")].GetDouble());
double delta(dEAngle - dSAngle);
AcDbVoidPtrArray regs;
parseSHProfile(v[_T("curve")], regs);
if (regs.isEmpty()) return;
bool bCombin(false);
std::vector<RegionGeom*> rgs;
analyRegions(regs, rgs, bCombin);
if (!bCombin)
{
AcDbRevolveOptions op;
for (int i(0); i < regs.length(); ++i)
{
AcDbRegion *pReg((AcDbRegion*)regs[i]);
solids.push_back(new NewRevolve(isSolid, pReg, pt, vt, delta, dSAngle));
}
}
else
{
std::sort(rgs.begin(), rgs.end(), RegionGeom::cmp);
RevitCombination *pRc = new RevitCombination();
pRc->m_bSolid = isSolid;
pRc->m_bOrderDraw = true;
AcDbRevolveOptions op;
for (int i(0); i < rgs.size(); ++i)
{
RegionGeom &rg(*rgs[i]);
AcDbRegion *pReg(rg.m_pSelf);
pRc->m_solids.push_back(new NewRevolve(!rg.m_bVoid, pReg, pt, vt, delta, dSAngle));
}
solids.push_back(pRc);
}
deleteArrayVoidPtrs< AcDbRegion>(regs);
deleteContainerOfStd(rgs);
}
void parseSHSweep(WCValue &v, std::vector<NewSolidBase*> &solids)
{
bool isSolid = v[_T("isSolid")].GetBool();
AcDbVoidPtrArray regs;
parseSHProfile(v[_T("curve")], regs);
if (regs.isEmpty()) return;
bool bCombin(false);
std::vector<RegionGeom*> rgs;
analyRegions(regs, rgs, bCombin);
AcDbEntity *pPath = parsePath((v[_T("path")])[_T("path")].GetArray());
if (!pPath) return;
AcDbPolyline *pPoly(AcDbPolyline::cast(pPath));
if (!pPoly)
{
DELETE_PTR(pPath);
return;
}
if (!bCombin)
{
for (int i(0); i < regs.length(); ++i)
{
AcDbRegion *pReg((AcDbRegion*)regs[i]);
solids.push_back(new NewSweepR(isSolid, pReg, pPoly));
}
}
else
{
std::sort(rgs.begin(), rgs.end(), RegionGeom::cmp);
RevitCombination *pRc = new RevitCombination();
pRc->m_bSolid = isSolid;
pRc->m_bOrderDraw = true;
for (int i(0); i < rgs.size(); ++i)
{
RegionGeom &rg(*rgs[i]);
AcDbRegion *pReg(rgs[i]->m_pSelf);
pRc->m_solids.push_back(new NewSweepR(!rg.m_bVoid, pReg, pPoly));
}
solids.push_back(pRc);
}
deleteArrayVoidPtrs< AcDbRegion>(regs);
deleteContainerOfStd(rgs);
DELETE_PTR(pPoly);
}
void parseSHNozzle(WCValue &v, std::vector<NewSolidBase*> &solids)
{
NewNozzle *pNozz = new NewNozzle;
pNozz->m_bSolid = true;
pNozz->m_nozz.bTwoFlags = 2;// 不需要绘制法兰
RVT_ConnectorProfileType Shape = (RVT_ConnectorProfileType)v[_T("m_Shape")].GetInt();
RVT_DOMAIN Domain = (RVT_DOMAIN)v[_T("m_Domain")].GetInt();
if (Shape == kRound)
{
if (Domain == kDomainHvac)
pNozz->m_nozz.nType = 2;
else
pNozz->m_nozz.nType = 0;
}
else if (Shape == kRectangular)
pNozz->m_nozz.nType = 1;
else
{
pNozz->m_nozz.nType = 0;
Shape = kRound;
acutPrintf(_T("\n出现上华软件不支持的管口!"));
DELETE_PTR(pNozz);
return;
}
if (Domain == kDomainPiping)
{
pNozz->m_nozz.nCmd = 0;
}
else if (Domain == kDomainHvac)
{
pNozz->m_nozz.nCmd = 1;
}
else
{
pNozz->m_nozz.nCmd = 0;
acutPrintf(_T("\n出现上华软件不支持的系统!"));
DELETE_PTR(pNozz);
return;
}
AcGeVector3d vtDir(parseVector3D(v[_T("m_Direction")]));
AcGePoint3d ptOrg(parsePoint3D(v[_T("m_Origin")]));
pNozz->m_ptOrg = ptOrg;
pNozz->m_vtDir = vtDir;
if (Shape == kRound)
{
pNozz->m_nozz.dVal1 = v[_T("m_dRadius")].GetDouble() * 2 * g_dUnitRate;
pNozz->m_nozz.dVal2 = pNozz->m_nozz.dVal1;
pNozz->m_nozz.dVal3 = pNozz->m_nozz.dVal1;
pNozz->m_nozz.dVal4 = pNozz->m_nozz.dVal1;
pNozz->m_nozz.dVal5 = .0;
solids.push_back(pNozz);
}
else if (Shape == kRectangular)
{
pNozz->m_nozz.dVal1 = v[_T("m_dWidth")].GetDouble() * g_dUnitRate;
pNozz->m_nozz.dVal2 = v[_T("m_dHeight")].GetDouble() * g_dUnitRate;
pNozz->m_nozz.dVal3 = 0.;
pNozz->m_nozz.dVal4 = 0.;
pNozz->m_nozz.dVal5 = 0.;
solids.push_back(pNozz);
}
else
DELETE_PTR(pNozz);
}
void parseSHGeo3D(WCValue &v, std::vector<NewSolidBase*> &ar)
{
std::wstring sType(v[_T("type")].GetString());
GeoType type = getGeoType(sType.c_str());
switch (type)
{
case kExtrusion:
return parseSHExtrusion(v, ar);
case kBlend:
return parseSHBlend(v, ar);
case kRevolution:
return parseSHRevolution(v, ar);
case kSweep:
return parseSHSweep(v, ar);
case kSweptBlend:
return parseSHSweptBlend(v, ar);
case kNozzle:
return parseSHNozzle(v, ar);
case kArc:
case kLine:
case kEllipse:
case kCylindricalHelix:
case kNurbSpline:
break;
case kBims:
case kNone:
default:
break;
}
return;
}
AcDbEntity* parseSHGeo2D(WCValue &v, GeoType &type, bool &isSolid)
{
std::wstring sType(v[_T("type")].GetString());
type = getGeoType(sType.c_str());
switch (type)
{
case kArc:
return parseSHArc(v);
case kLine:
return parseSHLine(v);
case kEllipse:
return parseSHEllipse(v);
case kCylindricalHelix:
return parseSHCylindricalHelix(v);
case kNurbSpline:
return parseSHNurbSpline(v);
case kExtrusion:
case kBlend:
case kRevolution:
case kSweep:
case kSweptBlend:
case kBims:
case kNone:
default:
break;
}
return NULL;
}
void parseSHProfile(WCValue &v, AcDbVoidPtrArray &regs, AcGePlane *pPlan)
{
if (pPlan) *pPlan = parseSHPlane(v[_T("plane")]);
GeoType type(__kNone);
bool isSolid(false);
AcDbVoidPtrArray curves;
const CArr &loops = v[_T("loops")].GetArray();
for (int i = 0; i < loops.Size(); ++i)
{
deleteArrayVoidPtrs< AcDbEntity>(curves);
const CArr &loop = loops[i][_T("loop")].GetArray();
for (int j = 0; j < loop.Size(); ++j)
{
WCValue &crv(loop[j]);
AcDbEntity *pCurve(parseSHGeo2D(crv, type, isSolid));
if (pCurve) curves.append(pCurve);
}
AcDbRegion *pReg(CoreTools::createRegion(curves));
#ifndef NDEBUG
if (!pReg)
{
for (int i = 0; i < curves.length(); ++i)
{
CoreTools::CloneAndAddToModelSpace((AcDbEntity*)curves[i], 1);
}
CoreTools::CloneAndAddToModelSpace(pReg, 1);
}
#endif // !NDEBUG
if (pReg)
regs.append(pReg);
}
deleteArrayVoidPtrs< AcDbEntity>(curves);
}
AcDbEntity* parsePath(const CArr &ar)
{
GeoType type1(__kNone), type2(__kNone);
bool isSolid(false);
AcDbVoidPtrArray crvs;
for (size_t i = 0; i < ar.Size(); ++i)
{
AcDbEntity *pCurve(parseSHGeo2D(ar[(rapidjson::SizeType)i], type1, isSolid));
if (!pCurve->isKindOf(AcDbCurve::desc())) continue;
AcDbEllipse *pEll(AcDbEllipse::cast(pCurve));
AcDb3dPolyline *p3dL(AcDb3dPolyline::cast(pCurve));
AcDbSpline *pSpline(AcDbSpline::cast(pCurve));
if (pEll || p3dL || pSpline)
{
AcDbPolyline *p = CoreTools::spliteCurve((AcDbCurve*)pCurve, 20);
if (p)
{
AcDbVoidPtrArray arr;
p->explode(arr);
crvs.append(arr);
}
}
else
crvs.append(pCurve);
}
AcDbPolyline *pL(NULL);
std::vector<AcDbPolyline*> polys;
if (CoreTools::MakePolyline(crvs, polys))
pL = (AcDbPolyline*)((AcDbPolyline*)polys[0]->clone());
deleteArrayVoidPtrs< AcDbEntity>(crvs);
deleteContainerOfStd(polys);
return pL;
}
bool parseJsonConfig(WDocument &doc)
{
MIt it = doc.FindMember(_T("Config"));
if (it == doc.MemberEnd())
{
AfxMessageBox(_T("未找到配置信息!"));
return false;
}
int __v(2);
g_nJsonVersion = it->value[_T("version")].GetInt();
if (g_nJsonVersion != __v)
{
CString str;
str.Format(_T("文件版本信息错误(当前版本为%d,文件版本为%d)"), __v, g_nJsonVersion);
AfxMessageBox(str);
return false;
}
g_dUnitRate = it->value[_T("UnitRate")].GetDouble();
return true;
}
void parseCombin(WCValue &v, std::vector<std::vector<CString>> &coms)
{
if (!v.IsArray()) return;
std::vector<CString> vec;
for (VCIt it = v.Begin(); it != v.End(); ++it)
{
vec.clear();
if (!it->IsObject()) continue;
MCIt itVoids = it->FindMember(_T("Voids"));
if (itVoids != it->MemberEnd())
{
if (itVoids->value.IsArray())
{
for (VCIt _it = itVoids->value.Begin(); _it != itVoids->value.End(); ++_it)
{
vec.push_back(_it->GetString());
}
}
}
MCIt itSolids = it->FindMember(_T("Solids"));
if (itSolids != it->MemberEnd())
{
if (itSolids->value.IsArray())
{
for (VCIt _it = itSolids->value.Begin(); _it != itSolids->value.End(); ++_it)
{
vec.push_back(_it->GetString());
}
}
}
coms.push_back(vec);
}
}
void parseGeos(WValue &v
, const std::vector<std::vector<CString>> &combs
, std::vector<NewSolidBase*> &geos)
{
if (!v.IsArray()) return;
// 处理一下combs,得到所有组合要用到的 uid
std::set<CString> uids;
for (size_t i(0); i < combs.size(); ++i)
{
const std::vector<CString> &vec(combs[i]);
for (size_t j(0); j < vec.size(); ++j)
uids.insert(vec[j]);
}
CString uid(_T(""));
for (VCIt it = v.Begin(); it != v.End();)
{
WCValue &va(*it);
if (!va.IsObject()) continue;
MCIt itID = va.FindMember(_T("elementId"));
if (itID == va.MemberEnd())
uid = _T("-1");
else
uid = itID->value.GetString();
if (uids.find(uid) == uids.end())
{
parseSHGeo3D(va, geos);
v.Erase(it);
it = v.Begin();
continue;
}
++it;
}
for (size_t i(0); i < combs.size(); ++i)
{
const std::vector<CString> &vec(combs[i]);
RevitCombination *pCmb = new RevitCombination();
for (size_t j(0); j < vec.size(); ++j)
{
for (VCIt it = v.Begin(); it != v.End(); ++it)
{
WCValue &va(*it);
if (!va.IsObject()) continue;
MCIt itID = va.FindMember(_T("elementId"));
if (itID == va.MemberEnd())
uid = _T("-1");
else
uid = itID->value.GetString();
if (uid != vec[j]) continue;
std::vector<NewSolidBase*> subgeos;
parseSHGeo3D(va, subgeos);
if (!subgeos.empty())
pCmb->m_solids.insert(pCmb->m_solids.end(), subgeos.begin(), subgeos.end());
break;
}
}
geos.push_back(pCmb);
}
}
}
void ParseRevitFamily::parseFile2String(LPCTSTR pszJson, std::wstring & json)
{
json.clear();
FILE *fp(NULL);
char *readBuffer(NULL);
fp = _tfopen(pszJson, _T("rb"));
if (!fp) return;
long fSize = getFileSize(fp);
++fSize;
readBuffer = new char[fSize];
::memset(readBuffer, 0, sizeof(char) * (fSize));
FileReadStream bis(fp, readBuffer, fSize);
AutoUTFInputStream<unsigned, FileReadStream> eis(bis);
WDocument doc;
doc.ParseStream<0, AutoUTF<unsigned> >(eis);
if (readBuffer) delete[] readBuffer;
if (fp) fclose(fp);
if (doc.HasParseError()) return;
WStringBuffer buffer;
Writer<WStringBuffer, UTF16<>, UTF16<>> writer(buffer);
doc.Accept(writer);
json = buffer.GetString();
}
void ParseRevitFamily::parseJson(std::wstring & json, CPtrArray &ar)
{
WDocument doc;
doc.Parse(json);
if (doc.HasParseError()) return;
if (doc.IsArray())
{ // 旧版本
std::vector<NewSolidBase*> _ar;
parseGeos(doc, std::vector<std::vector<CString>>(), _ar);
Adesk::Int32 id = ::_time32(NULL);
for (int i(0); i < _ar.size(); ++i)
{
ar.Add(NewSolidBase::makeXPrimData(_ar[i], id++));
}
deleteContainerOfStd(_ar);
return;
}
if (!parseJsonConfig(doc)) return;
// 先把 GeomCombination 处理一下
MIt itComs = doc.FindMember(_T("Combin"));
if (itComs == doc.MemberEnd()) return;
std::vector<std::vector<CString>> jsoncoms;
parseCombin(itComs->value, jsoncoms);
MIt itGeos = doc.FindMember(_T("Geos"));
if (itGeos == doc.MemberEnd()) return;
std::vector<NewSolidBase*> _ar;
parseGeos(itGeos->value, jsoncoms, _ar);
Adesk::Int32 id = ::_time32(NULL);
for (int i(0); i < _ar.size(); ++i)
{
ar.Add(NewSolidBase::makeXPrimData(_ar[i], id++));
}
deleteContainerOfStd(_ar);
}
void ParseRevitFamily::parseBimDatas(std::wstring &json, SH_BIM_BLOCK &bims)
{
WDocument doc;
doc.Parse(json);
if (doc.HasParseError()) return;
if (doc.IsArray())
{ // 旧版本
for (VCIt it = doc.Begin(); it != doc.End(); ++it)
{
if (!it->IsObject()) continue;
WCValue &v(*it);
std::wstring sType(v[_T("type")].GetString());
GeoType type = getGeoType(sType.c_str());
if (type != kBims) continue;
WCValue &jbims = v[_T("bims")];
WCValue::ConstMemberIterator bit = jbims.MemberBegin();
std::wstring name, value;
for (; bit != jbims.MemberEnd(); ++bit)
{
name = bit->name.GetString();
value = bit->value.GetString();
bims.push_back(std::make_pair(name.c_str(), value.c_str()));
}
}
return;
}
if (!parseJsonConfig(doc)) return;
std::map<CString, std::vector<std::pair<CString, CString>>> bimDatas;
MIt itBims = doc.FindMember(_T("Bims"));
if (itBims == doc.MemberEnd()) return;
WValue &vBims = itBims->value;
GeoType type = getGeoType(vBims[_T("type")].GetString());
if (type != kBims) return;
WCValue &jbims = vBims[_T("bims")];
MCIt itGrp = jbims.MemberBegin();
std::wstring sGrpName, value;
std::vector<std::pair<CString, CString>> vv;
for (; itGrp != jbims.MemberEnd(); ++itGrp)
{
sGrpName = itGrp->name.GetString();
WCValue &vGrp(itGrp->value);
MCIt it = vGrp.MemberBegin();
vv.clear();
for (; it != vGrp.MemberEnd(); ++it)
{
if (!it->value.IsNull())
vv.push_back(std::make_pair(it->name.GetString(), it->value.GetString()));
}
bimDatas.insert(std::make_pair(sGrpName.c_str(), vv));
}
// 取 PG_MECHANICAL, PG_MATERIALS, PG_GENERAL, PG_GEOMETRY
std::map<CString, std::vector<std::pair<CString, CString>>>::const_iterator _it(bimDatas.end());
_it = bimDatas.find(_T("PG_MECHANICAL"));
if (_it != bimDatas.end())
{
const std::vector<std::pair<CString, CString>> &v(_it->second);
bims.insert(bims.end(), v.begin(), v.end());
}
_it = bimDatas.find(_T("PG_MATERIALS"));
if (_it != bimDatas.end())
{
const std::vector<std::pair<CString, CString>> &v(_it->second);
bims.insert(bims.end(), v.begin(), v.end());
}
_it = bimDatas.find(_T("PG_GENERAL"));
if (_it != bimDatas.end())
{
const std::vector<std::pair<CString, CString>> &v(_it->second);
bims.insert(bims.end(), v.begin(), v.end());
}
_it = bimDatas.find(_T("PG_GEOMETRY"));
if (_it != bimDatas.end())
{
const std::vector<std::pair<CString, CString>> &v(_it->second);
bims.insert(bims.end(), v.begin(), v.end());
}
}