BIMBase C++二次开发 调用PlaneGCS求解直线约束

之前有手写的约束求解(CSDNBMBase二次开发 C++ 创建直线约束求解器_bpentitycr-CSDN博客CSDN),但是在涉及到跨对象约束太多的时候,就会产生很多计算上的错误。所以现在改用了调用PlaneGCS来求解(PlaneGCS包下载地址:FreeCAD/src/Mod/Sketcher/App/planegcs at main · FreeCAD/FreeCAD · GitHub)。用PlaneGCS来求解,只需要把约束添加到求解器里面,然后求解,如果求解成功,那么再把求解器里面的参数赋值到BIMBase里面的自定义直线上,并且更新约束图像,就完成了约束。也参考了PlaneGCS-平面几何约束求解器用法 - opencascade - 博客园 (cnblogs.com)这篇文章,后续就是自己慢慢摸索调试修改完后的内容。

1.添加约束参数到求解器    

                    GCS::Point aP1(new double(pbLine.getStartPoint().x), new double(pbLine.getStartPoint().y));
					GCS::Point aP2(new double(pbLine.getEndPoint().x), new double(pbLine.getEndPoint().y));
					GCS::Line aLine1;
					aLine1.p1 = aP1;
					aLine1.p2 = aP2;

					aParameters.push_back(aLine1.p1.x);
					aParameters.push_back(aLine1.p1.y);
					aParameters.push_back(aLine1.p2.x);
					aParameters.push_back(aLine1.p2.y);

					int lineId = pbLine.m_nLineId;
					// 插入时使用 make_unique 或 make_shared
					Line_GCS.insert(std::make_pair(lineId, std::make_unique<GCS::Line>(aLine1)));

2.添加约束

由于PlaneGCS并没有水平距离、垂直距离和共点这些约束,只有倍数相等,差值等约束,所以在添加所叙的这些约束时,就需要用它的已有约束去构造这些约束。

switch (nConstraintType)
	{
	case 1://水平距离
	{
		if (nLineNum != -1 && nNextGraphicElementID <= 0)//与原点的约束
		{
			nRet = aSolver.addConstraintDifference(aP1.x, aP2.x, new double(dConstrainValue));
			GCS::Constraint* constr6 = new GCS::ConstraintEqual(aP1.x, new double(0.00));
			nRet = aSolver.addConstraint(constr6);
			GCS::Constraint* constr7 = new GCS::ConstraintEqual(aP1.y, new double(0.00));
			nRet = aSolver.addConstraint(constr7);
			aParameters.push_back(new double(0.00));
		}
		else if (nConstraintDim_ID == nLineID || nNextGraphicElementID <= 0)
			nRet = aSolver.addConstraintDifference(aP1.x, aP2.x, new double(dConstrainValue));
		else
			nRet = aSolver.addConstraintDifference(aP2.x, aP1.x, new double(dConstrainValue));
		aParameters.push_back(new double(dConstrainValue));
		return  nRet;
	}
	case 2://垂直距离
	{
		if (nLineNum != -1 && nNextGraphicElementID <= 0)//与原点的约束
		{
			nRet = aSolver.addConstraintDifference(aP1.y, aP2.y, new double(dConstrainValue));
			GCS::Constraint* constr6 = new GCS::ConstraintEqual(aP1.x, new double(0.00));
			nRet = aSolver.addConstraint(constr6);
			GCS::Constraint* constr7 = new GCS::ConstraintEqual(aP1.y, new double(0.00));
			nRet = aSolver.addConstraint(constr7);
			aParameters.push_back(new double(0.00));
		}
		else if (nConstraintDim_ID == nLineID || nNextGraphicElementID <= 0)
			nRet = aSolver.addConstraintDifference(aP1.y, aP2.y, new double(dConstrainValue));
		else
			nRet = aSolver.addConstraintDifference(aP2.y, aP1.y, new double(dConstrainValue));
		aParameters.push_back(new double(dConstrainValue));
		return  nRet;
	}
	case 3://水平
	{
		GCS::Constraint* constr = new GCS::ConstraintEqual(aP1.y, aP2.y);
		nRet = aSolver.addConstraint(constr);
		return nRet;
	}
	case 4://垂直
	{
		GCS::Constraint* constr = new GCS::ConstraintEqual(aP1.x, aP2.x);
		nRet = aSolver.addConstraint(constr);
		return nRet;
	}
	case 5://共点
	{
		GCS::Constraint* constr1 = new GCS::ConstraintEqual(aP1.x, aP2.x);
		GCS::VEC_pD vecParam1 = constr1->params();
		for (auto iter_param : vecParam1)
			aParameters.push_back(iter_param);

		GCS::Constraint* constr2 = new GCS::ConstraintEqual(aP1.y, aP2.y);
		GCS::VEC_pD vecParam2 = constr2->params();
		for (auto iter_param : vecParam2)
			aParameters.push_back(iter_param);

		aSolver.addConstraint(constr1);
		nRet = aSolver.addConstraint(constr2);
		return nRet;
		
	}
}

3.约束求解和赋值给BIMBase的自定义直线

在上面的添加约束参数到求解器 这一步的时候,就把参数添加到aParameters,由于都是指针,求解完后只就把这些指针指向的值拿出来赋值给里自定义直线,然后直线再调用::p3d::P3DStatus       replaceInProject(::BIMBase::Core::BPProjectR project, bool bReCreateGeometry = true)这个函数把直线刷新到求解完以后的正确位置。下述代码就没有再写求解失败的代码,一般求解石板就直接返回false。

if(aSolver.solve(aParameters) == GCS::Success)//约束求解
{
    for (const auto& pair : Line_GCS)//把Line_GCS里的值赋值给自定义直线
		{
			int lineId = pair.first;
			GCS::Curve* curvePtr = pair.second.get();
			//if (1/*entity.getclassname == L"ATDLine"*/)

			GCS::Line* linePtr = dynamic_cast<GCS::Line*>(curvePtr);
			BPEntityId GeometryID(modelidd, lineId);
			BPEntityPtr ptrEntityLine = pProject->getEntityById(GeometryID);
			if (!ptrEntityLine.isValid())
				return false;

			BPDataPtr ptrData = BPDataUtil::getDataOnEntity(*ptrEntityLine);
			if (!ptrData.isValid())
				return false;

			LineDemo pbline;
			pbline.initFromData(*ptrData);

			pbline.setStartPoint(GePoint3d::create(*linePtr->p1.x, *linePtr->p1.y, 0));
			pbline.setEndPoint(GePoint3d::create(*linePtr->p2.x, *linePtr->p2.y, 0));
			pbline.replaceInProject(*pProject);
		}
    
    for (auto itre_EntID : vecEntID)//约束图像更新位置
		{
			BPDataPtr ptrData = ATiDeConstraint::getBPdataByEntityID(itre_EntID, pProject, modelidd);
			LineDemo pbLine;
			pbLine.initFromData(*ptrData);
			strAppName.Format(_T("%s_Id=%d"), L"ATDLine", pbLine.getLineId());
			int nConstraintcount = GetPrivateProfileInt(strAppName, _T("ConstraintCount"), 0, PBM_Constraint_INIFile_Path);
			if (nConstraintcount <= 0)
				return  false;
			int j = 0;
			for (int i = 1; ; i++)
			{
				strKey.Format(_T("Constrain_%d"), i);
				int nConstraintType = GetPrivateProfileInt(strAppName, strKey, 0, PBM_Constraint_INIFile_Path);
				if (nConstraintType == 0)//当前约束不存在(有可能被删除)
					continue;
				j++;

				//读取约束值
				double dConstrainValue = 0.0;
				TCHAR szValue[MAX_PATH + 1] = _T("");
				strKey.Format(_T("Constrain_Value_%d"), i);
				::GetPrivateProfileString(strAppName, strKey, _T("0"), szValue, MAX_PATH, PBM_Constraint_INIFile_Path);
				strValue.Format(_T("%s"), szValue);
				dConstrainValue = _wtof(strValue.GetBuffer());

				strKey.Format(_T("Constrain_LineNum_%d"), i);
				int nLineNum = GetPrivateProfileInt(strAppName, strKey, 0, PBM_Constraint_INIFile_Path);

				strKey.Format(_T("Constrain_NextGraphicElementID_%d"), i);
				int nNextGraphicElementID = GetPrivateProfileInt(strAppName, strKey, 0, PBM_Constraint_INIFile_Path);

				strKey.Format(_T("Constrain_DataID_%d"), i);
				int nDimDataID = GetPrivateProfileInt(strAppName, strKey, 0, PBM_Constraint_INIFile_Path);
				strKey.Format(_T("Constrain_ClassID_%d"), i);
				int nDimClassID = GetPrivateProfileInt(strAppName, strKey, 0, PBM_Constraint_INIFile_Path);
				BPDataKey ptrDimDataKey(nDimClassID, BPDataId(nDimDataID));
				BPDataPtr ptrDimData = BPDataUtil::getDataByKey(ptrDimDataKey, *pProject);
				ConstraintDimensionP CTDim = new ConstraintDimension();
				CTDim->initFromData(*ptrDimData);
				CTDim->m_dDimensionValue = dConstrainValue;
				switch (nConstraintType)
				{
				case 1:
				case 2:
				{
					if (nNextGraphicElementID <= 0 && nLineNum == -1)
					{
						CTDim->m_ptStart = pbLine.getStartPoint();
						CTDim->m_ptEnd = pbLine.getEndPoint();
					}
					else if (nNextGraphicElementID <= 0 && nLineNum != -1)
					{
						CTDim->m_ptStart = GePoint3d::create(0, 0, 0);
						CTDim->m_ptEnd = (nLineNum == 0) ? pbLine.getStartPoint() : pbLine.getEndPoint();
					}
					else
					{
						strKey.Format(_T("Constrain_LineNum_%d"), i);
						int nLineNum = GetPrivateProfileInt(strAppName, strKey, -1, PBM_Constraint_INIFile_Path);
						if (nLineNum == 0 || nLineNum == 1)
							CTDim->m_ptStart = (nLineNum == 0) ? pbLine.getStartPoint() : pbLine.getEndPoint();

						BPDataPtr ptrNextData = ATiDeConstraint::getBPdataByEntityID(nNextGraphicElementID, pProject, modelidd);
						LineDemo pbNextLine;
						pbNextLine.initFromData(*ptrNextData);
						strKey.Format(_T("Constrain_NextLineNum_%d"), i);
						int nLineNextNum = GetPrivateProfileInt(strAppName, strKey, -1, PBM_Constraint_INIFile_Path);
						if (nLineNextNum == 0 || nLineNextNum == 1)
							CTDim->m_ptEnd = (nLineNextNum == 0) ? pbNextLine.getStartPoint() : pbNextLine.getEndPoint();
					}
					break;
				}
				case 3:
				case 4:
				{
					CTDim->m_ptStart = pbLine.getStartPoint();
					CTDim->m_ptEnd = pbLine.getEndPoint();
					break;
				}
				case 5:
				{
					CTDim->m_ptStart = pbLine.getStartPoint();
					CTDim->m_ptEnd = pbLine.getEndPoint();

					strKey.Format(_T("Constrain_LineNum_%d"), i);
					int nLineNum = GetPrivateProfileInt(strAppName, strKey, -1, PBM_Constraint_INIFile_Path);
					CTDim->m_nPtOnNum = nLineNum;

					break;
				}
				default:
				{
					AfxMessageBox(ATD_Constraint_Exist_Constraint);
					break;
				}
				}
				CTDim->replaceInProject(*pProject);

				//在这结束循环
				if (j >= nConstraintcount)
					break;
			}
		}
}

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值