|
|
#include "pch.h"
#include "EleLine.h"
#include "FuncBase.h"
#include "MathHelper.h"
#include "LineConstructLog.h"
#include "ElePlane.h"
#include "EleGap.h"
#include "ElePointCloud.h"
#include "Alignment.h"
#include <algorithm>
#include "EleEllipse.h"
#include <unordered_set>
/// <summary>
/// 初始化
/// </summary>
/// <param name="count"></param>
/// <param name="uid"></param>
/// <param name="vectors"></param>
void EleLine::EleInit(int count, string uid, ShapeRecognition vectors)
{
CElementBase::Init();
this->m_strElementUid = uid;
this->nType = ELE_LINE;
this->m_strTypeName = "Line";
this->m_nIndex = count + 1;
if (vectors.IsScan)
{
mcs_Start = vectors.LeftTopPo;
mcs_End = vectors.BottomRightPo;
m_pMCS->McsPosition = (vectors.LeftTopPo.XYZ() + vectors.BottomRightPo.XYZ()) * 0.5;
Length = mcs_Start.Distance(mcs_End);
PointF = vectors.McsPointF;
this->m_bIsScan = vectors.IsScan;
}
}
/// <summary>
/// 克隆
/// </summary>
/// <returns></returns>
CElementBase* EleLine::Clone()
{
CElementBase* ptr = new EleLine(*this);
ptr->Init();
ptr->m_pMCS->McsPosition = this->m_pMCS->McsPosition;
ptr->m_pMCS->McsLeftPoint = this->m_pMCS->McsLeftPoint;
ptr->m_pMCS->McsRightPoint = this->m_pMCS->McsRightPoint;
ptr->m_pPCS->PcsPosition = this->m_pPCS->PcsPosition;
return ptr;
}
/// <summary>
/// 绘制
/// </summary>
/// <returns></returns>
Handle(MyInteractiveObject) EleLine::Draw(double zoomFactor)
{
gp_Pnt startP = this->mcs_Start;
gp_Pnt endP = this->mcs_End;
if (startP.XYZ().IsEqual(endP.XYZ(), 1.0e-9))
return nullptr;
//处理特征偏移
auto points = FuncBase::ElementOffset(this);
if (points.size() > 0)
{
startP = points[0];
endP = points[1];
}
TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(startP);
TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(endP);
TopoDS_Shape aShape = BRepBuilderAPI_MakeEdge(V1, V2);
Handle(MyInteractiveObject) aisLine = new MyInteractiveObject(aShape);
return aisLine;
}
Handle(MyInteractiveObject) EleLine::DrawLable(string name, gp_Pnt& firstPt)
{
vector<gp_Pnt> myPoints = PointF;
if (myPoints.size() < 3)
{
myPoints.clear();
myPoints.push_back(this->mcs_Start);
myPoints.push_back(this->mcs_End);
myPoints.push_back(this->m_pMCS->McsPosition);
}
int randomIndex = GenerateRandomIndex(0, static_cast<int>(myPoints.size()) - 1);
gp_Pnt startPo = GetSubPoint(myPoints.at(randomIndex));
startPo = FuncBase::GetMatrixPoint(this, startPo);
// 角度参数θ
double theta = GenerateRandomAngle(); // 比如θ = 45度,即π/4
// 计算圆上点的坐标
double x = startPo.X() + 3 * cos(theta);
double y = startPo.Y() + 3 * sin(theta);
gp_Pnt pointCir = gp_Pnt(x, y, startPo.Z());
gp_Vec avgVec = gp_Vec(startPo, pointCir).Normalized();
if (avgVec.Y() == 0) //平行与X轴
{
avgVec = gp_Vec(0, 1, 0);
}
else if (avgVec.X() == 0) //平行与Y轴
{
avgVec = gp_Vec(1, 0, 0);
}
gp_Pnt endPo1 = startPo.XYZ() + (avgVec * 4).XYZ();
gp_Pnt lablePos = startPo.XYZ() + (avgVec * 4.5).XYZ();
firstPt = startPo;
TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(startPo);
TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(endPo1);
TopoDS_Shape aShape = BRepBuilderAPI_MakeEdge(V1, V2);
Handle(MyInteractiveObject) eleLable = new MyInteractiveObject(aShape);
Handle(AIS_TextLabel) lable = new AIS_TextLabel();
lable->SetPosition(lablePos);
lable->SetZoomable(false);
lable->SetColor(Quantity_NOC_YELLOW);
TCollection_ExtendedString tostr;
Resource_Unicode::ConvertGBToUnicode(name.c_str(), tostr);
lable->SetText(tostr);
eleLable->SetTextLabel(lable);
return eleLable;
}
/// <summary>
/// 获取最近点
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
gp_Pnt EleLine::GetSubPoint(gp_Pnt point)
{
gp_Vec dirction = gp_Vec(mcs_Start, mcs_End);
gp_Vec poToStart = gp_Vec(mcs_Start, point);
// 计算投影参数 t
double t = dirction.Dot(poToStart) / dirction.Dot(dirction);
// 计算投影点 p
gp_Pnt p = mcs_Start.XYZ() + (t * dirction).XYZ();
return p;
}
void EleLine::ResetConSubPoints(CElementBase* parentEle)
{
CElementBase::ResetConSubPoints(parentEle);
int i = 0;
GeomAdaptor_Curve myCurve = GetCurve();
if (PointF.size() < 3 || myCurve.Curve().IsNull())
{
return;
}
else
{
double dmax = 0;
double dmin = 0;
for (gp_Pnt p : this->PointF)
{
try
{
if(this->m_elementOffset.m_bIsOffseted)
p = FuncBase::GetMatrixPoint(this, p);
gp_Pnt subPt = FindClosestPointOnCurve(myCurve, p);
gp_Pnt pcsSubPt = FuncBase::ConvertToV2(parentEle, subPt);
gp_Pnt pcsP = FuncBase::ConvertToV2(parentEle, p);
FuncBase::SetPcsPoint(parentEle, pcsSubPt, pcsP);
subPt = FuncBase::ConvertPcsToMcs(parentEle, pcsSubPt);
int index = MathHelper::returnRightOrLeft(mcs_Start, mcs_End, p);
double distance = subPt.Distance(p);
Distances.push_back(distance);
if (index == 2)
distance = -distance;
this->ConSubPoints.push_back({ p ,subPt,distance, Quantity_Color(Quantity_NOC_WHEAT) });
gp_Vec realVec = gp_Vec(mcs_Start, p);
gp_Vec lineVec = gp_Vec(mcs_Start, mcs_End);
double s = (realVec.X() * lineVec.Y() - realVec.Y() * lineVec.X()) >= 0. ? 1 : -1;
distance = s * distance;
if (0 == i)
{
dmax = dmin = distance;
}
i++;
if (distance > dmax)
dmax = distance;
if (distance < dmin)
dmin = distance;
}
catch (const std::exception& e)
{
std::ignore = e;
continue;
}
}
this->MaxOffset = to_string(dmax);
this->MinOffset = to_string(dmin);
}
CElementBase::FiltFit();
}
/// <summary>
/// 执行构造
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <param name="elements"></param>
/// <param name="fullElements"></param>
/// <returns></returns>
bool EleLine::ExecuteTools(vector<CElementBase*> selectEles,
CElementBase* parentEle, bool isMulPoint, int fitMethod)
{
bool ret = false;
auto tempTooltype = vecToolTypes;
map<ToolType, bool>::iterator itAu;
map<ToolType, bool>::iterator itmid;
vector<gp_Pnt> myAddPts;
std::list<ToolsInput>::iterator itav;
for (auto it = tempTooltype.begin(); it != tempTooltype.end(); ++it)
{
auto uesedKeyValue = IsUesedToolTypes.find(*it);
if (uesedKeyValue != IsUesedToolTypes.end()) //&& !uesedKeyValue->second
{
auto mdIt = IsUesedToolTypes.find(MidPointComposition);
auto auIt = IsUesedToolTypes.find(AutomaticDecision);
auto bisIt = IsUesedToolTypes.find(Bisector);
switch (*it)
{
case AutomaticDecision: //已改
//存在平分和自动判断时,平分已构造完成则不需要走自动判断
if (bisIt != IsUesedToolTypes.end() && IsUesedToolTypes[Bisector]) break;
if (selectEles.size() == 2 && (selectEles.at(0) == selectEles.at(1)))
{
selectEles.pop_back();
}
ret = AutomaticLine(selectEles, parentEle, myAddPts, fitMethod);
if (mdIt != IsUesedToolTypes.end())
{
for (auto tools : this->toolTypes[ToolType::MidPointComposition])
{
itav = find_if(this->toolTypes[ToolType::AutomaticDecision].begin(), this->toolTypes[ToolType::AutomaticDecision].end(),
[tools](const ToolsInput tool) {
return tool.InputEleID._Equal(tools.InputEleID);
});
// 查找特征
// 如果找到了该特征
if (itav != this->toolTypes[ToolType::AutomaticDecision].end())
this->toolTypes[ToolType::AutomaticDecision].erase(itav); // 移除特征
}
}
break;
case Bisector: //已改
ret = LineBisector(selectEles, parentEle);
break;
case Vertical: //已改
if(!IsUesedToolTypes[Vertical])
ret = LineVertical(*(--selectEles.end()), parentEle);
break;
case Parallel: //已改
if (!IsUesedToolTypes[Parallel])
ret = LineParalle(*(--selectEles.end()), parentEle);
break;
case MidPointComposition: //已改
if (uesedKeyValue->second )
{
if (selectEles.size() == 0)
ret = true;
string curUid = selectEles.at(0)->m_strElementUid;
list<ToolsInput> listInput = toolTypes[*it];
auto findit = find_if(listInput.begin(), listInput.end(),
[curUid](const ToolsInput tool) {
return tool.InputEleID._Equal(curUid);
});
if (findit != listInput.end())
break;
else
{
ret = true;
}
}
ret = LineMidPointComposition(selectEles, parentEle);
if (auIt != IsUesedToolTypes.end())
{
for (auto tools : this->toolTypes[ToolType::AutomaticDecision])
{
itav = find_if(this->toolTypes[ToolType::MidPointComposition].begin(), this->toolTypes[ToolType::MidPointComposition].end(),
[tools](const ToolsInput tool) {
return tool.InputEleID._Equal(tools.InputEleID);
});
// 查找特征
// 如果找到了该特征
if (itav != this->toolTypes[ToolType::MidPointComposition].end())
this->toolTypes[ToolType::MidPointComposition].erase(itav); // 移除特征
}
}
break;
case Cross:
ret = LineCorss(selectEles, parentEle); //不需要改动 工作平面
break;
case TangentLine:
ret = LineTange(selectEles, parentEle); //已改
break;
case MinimumRange:
ret = LineMinimunRange(selectEles, parentEle);
break;
case ToolType::callOut:
ret = CallOutLine(selectEles[0], parentEle); break;
default: break;
}
}
if (uesedKeyValue == IsUesedToolTypes.end()) continue;
auto it1 = IsUesedToolTypes.find(uesedKeyValue->first);
if (!mcs_Start.IsEqual(mcs_End, 1e-6) && !mcs_Start.IsEqual(gp_Pnt(0, 0, 0), 1e-6) && !mcs_End.IsEqual(gp_Pnt(0, 0, 0), 1e-6)
&& (it1 == IsUesedToolTypes.end() || !it1->second))
this->IsUesedToolTypes[uesedKeyValue->first] = true;
}
ResetConSubPoints(parentEle);
return ret;
}
bool EleLine::FiltFitShape(vector<gp_Pnt>& contourPos, int& removeCount)
{
bool ret = CElementBase::FiltFitShape(contourPos, removeCount);
if (!ret)
return false;
ret = FitLine(contourPos, this->parentCoordnate, this->mcs_Start, this->mcs_End, 0);
if (ret)
{
Distances.clear();
double dmax = 0;
double dmin = 0;
int i = 0;
GeomAdaptor_Curve myCurve = GetCurve();
if (myCurve.Curve().IsNull())
{
return ret;
}
for (auto& myPairs : this->ConSubPoints)
{
try
{
gp_Pnt pt = get<0>(myPairs);
gp_Pnt subPt = FindClosestPointOnCurve(myCurve, pt);
gp_Pnt pcsSubPt = FuncBase::ConvertToV2(parentCoordnate, subPt);
gp_Pnt pcsP = FuncBase::ConvertToV2(parentCoordnate, pt);
FuncBase::SetPcsPoint(parentCoordnate, pcsSubPt, pcsP);
subPt = FuncBase::ConvertPcsToMcs(parentCoordnate, pcsSubPt);
int index = MathHelper::returnRightOrLeft(mcs_Start, mcs_End, pt);
double distance = subPt.Distance(pt);
Distances.push_back(distance);
if (index == 2)
distance = -distance;
myPairs = std::make_tuple(pt, subPt, distance, get<3>(myPairs));
gp_Vec realVec = gp_Vec(mcs_Start, pt);
gp_Vec lineVec = gp_Vec(mcs_Start, mcs_End);
double s = (realVec.X() * lineVec.Y() - realVec.Y() * lineVec.X()) >= 0. ? 1 : -1;
distance = s * distance;
if (0 == i)
{
dmax = dmin = distance;
}
i++;
if (distance > dmax)
dmax = distance;
if (distance < dmin)
dmin = distance;
}
catch (const std::exception& e)
{
std::ignore = e;
continue;
}
}
this->MaxOffset = to_string(dmax);
this->MinOffset = to_string(dmin);
CElementBase::FiltFitShape(contourPos, removeCount); //最后再排除下过滤点
}
return ret;
}
/// <summary>
/// 特征判断
/// </summary>
/// <param name="elementType"></param>
/// <param name="toolType"></param>
/// <returns></returns>
bool EleLine::EleJudge(ElementType elementType, ToolType toolType)
{
switch (toolType)
{
case ToolType::AutomaticDecision:
return true;
case ToolType::PointsInput:
return true;
case ToolType::MidPointComposition:
switch (elementType)
{
case ELE_PLANE: return false;
case ELE_OPEN_CLOUD_LINE: return false;
case ELE_POINT_CLOUD: return false;
default: return true;
}
case ToolType::Cross:
switch (elementType)
{
case ELE_PLANE: return true;
default: return false;
}
case ToolType::Bisector:
switch (elementType)
{
case ELE_PLANE: return false;
case ELE_OPEN_CLOUD_LINE: return false;
case ELE_POINT_CLOUD: return false;
default: return true;
}
case ToolType::Vertical:
switch (elementType)
{
case ELE_LINE: return true;
case ELE_ELLIPSE: return true;
case ELE_GAP: return true;
case ELE_DISTANCE: return true;
case ELE_RECTANGLE: return true;
default: return false;
}
case ToolType::Parallel:
switch (elementType)
{
case ELE_LINE: return true;
case ELE_RECTANGLE: return true;
case ElE_COORDINATION_SYSTME: return true;
case ELE_GAP: return true;
case ELE_DISTANCE: return true;
default: return false;
}
case ToolType::TangentLine:
switch (elementType)
{
case ELE_CIRCLE: return true;
case ELE_ARC: return true;
case ELE_ELLIPSE: return true;
default: return false;
}
case ToolType::MinimumRange:
switch (elementType)
{
case ELE_POINT: return true;
case ELE_LINE: return true;
case ELE_OPEN_CLOUD_LINE: return true;
default: return false;
}
default: return false;
}
}
/// <summary>
/// 自动判断
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::AutomaticLine(vector<CElementBase*> selectEles, CElementBase* parentEle,vector<gp_Pnt> addPoints,int fitMethod)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
if (selectEles.at(0))
this->PointF.clear();
this->ParentUid = parentEle->m_strElementUid;
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
vector< int> myCloudLineIndexs;
for (int i = 0; i < selectEles.size(); i++)
{
if (this->m_listComponentElements.size() > 0)
{
ComponentEle* mySegement = nullptr;
selectEles->PointF.clear();
for (auto comPonent : this->m_listComponentElements)
{
if (comPonent->IsSegementCom)
mySegement = comPonent;
if (mySegement != nullptr && selectEles->m_strElementUid == mySegement->m_strComponentUid)
{
vector<gp_Pnt> mySePts = ((EleOpenCloudLine*)selectEles)->ExtractSegmentFromCloudPoints(mySegement->SegementPts.at(0), mySegement->SegementPts.at(1), mySegement->IsOtherEdge);
selectEles->PointF.insert(selectEles->PointF.end(), mySePts.begin(),
mySePts.end());
}
else
{
continue;
}
}
}
}
if (selectEles.size() == 1 && (selectEles.at(0)->nType == ELE_LINE || selectEles.at(0)->nType == ELE_POINT || selectEles.at(0)->nType == ElE_COORDINATION_SYSTME || selectEles.at(0)->nType == ELE_POINT_CLOUD))
{
if (!vec_Line.IsEqual(gp_Vec(0, 0, 0), 1.0e-9, 1.0e-9))
{
string toolName = ToolTypeToString(ToolType::PointsInput);
if (selectEles.at(0)->nType == ELE_LINE)
{
this->Length = ((EleLine*)selectEles.at(0))->Length;
this->PointF.insert(this->PointF.end(), selectEles.at(0)->PointF.begin(), selectEles.at(0)->PointF.end());
}
else
{
toolName = ToolTypeToString(ToolType::MidPointComposition);
}
gp_Dir normal = myPlane.Axis().Direction();
// 2. 计算向量在法向量方向上的分量(点积 * 法向量)
double dot = vec_Line.Dot(normal);
gp_Vec normalComponent = normal.XYZ() * dot;
// 3. 减去垂直分量,得到平面上的投影
gp_Vec projectedVec = vec_Line - normalComponent;
projectedVec.Normalize();
this->m_pMCS->McsPosition = selectEles.at(0)->GetMcsPosition();
this->mcs_Start = this->m_pMCS->McsPosition.XYZ() + (projectedVec * this->Length * 0.5f).XYZ();
this->mcs_End = this->m_pMCS->McsPosition.XYZ() - (projectedVec * this->Length * 0.5f).XYZ();
this->vec_Line = gp_Vec(0, 0, 0);
this->PointF.push_back(mcs_Start);
this->PointF.push_back(mcs_End);
toolsInputs.push_back(ToolsInput{ toolName, selectEles.at(0)->m_strElementName,selectEles.at(0)->m_strElementUid });
}
else
{
bool retemp = LinePointsInput(selectEles, parentEle, toolsInputs, addPoints, AutomaticDecision, fitMethod);
if (!retemp)
{
exception ex;
throw ex;
}
}
}
else if((selectEles.size() == 2) && (selectEles.at(0)->nType != ELE_LINE || selectEles.at(1)->nType != ELE_LINE))
{
if (toolTypes[ToolType::AutomaticDecision].size() > 0)
{
string tName = toolTypes[ToolType::AutomaticDecision].begin()->ToolName;
if (tName.find(ToolTypeToString(ToolType::TangentLine)) != std::string::npos)
{
vector<CElementBase*> solutions;
//圆圆切线
if (selectEles.at(1)->nType == ELE_CIRCLE || selectEles.at(1)->nType == ELE_ARC)
{
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), selectEles.at(0)->m_strElementName, selectEles.at(0)->m_strElementUid });
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), selectEles.at(1)->m_strElementName, selectEles.at(1)->m_strElementUid });
solutions = PointCircleTangenLine(this, selectEles.at(0), selectEles.at(1)->GetMcsPosition(), selectEles, parentEle, true);
}
else//点圆切线
{
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), selectEles.at(0)->m_strElementName, selectEles.at(0)->m_strElementUid });
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::MidPointComposition), selectEles.at(1)->m_strElementName, selectEles.at(1)->m_strElementUid });
solutions = PointCircleTangenLine(this, selectEles.at(0), selectEles.at(1)->GetMcsPosition(), selectEles, parentEle, false);
}
//后续返回线段(用特征得id代表)
if (mySolutCallback && m_nSolutionIndex == -1)
mySolutCallback(solutions);
else
{
EleLine* ele_Line = (EleLine*)solutions.at(m_nSolutionIndex);
this->mcs_Start = ele_Line->mcs_Start;
this->mcs_End = ele_Line->mcs_End;
this->Length = ele_Line->Length;
this->m_pMCS->McsPosition = ele_Line->m_pMCS->McsPosition;
this->m_pPCS->PcsPosition = ele_Line->m_pPCS->PcsPosition;
this->m_elementOffset.BefMcsPoint = ele_Line->m_elementOffset.BefMcsPoint;
}
this->toolTypes[ToolType::TangentLine] = toolsInputs;
this->IsUesedToolTypes[TangentLine] = true;
return true;
}
}
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::MidPointComposition), selectEles.at(0)->m_strElementName, selectEles.at(0)->m_strElementUid });
string toolName = ToolTypeToString(ToolType::MidPointComposition);
PointF.clear();
PointF.push_back(selectEles.at(0)->GetMcsPosition());
vector<gp_Pnt> listPoints = PointF;
tuple<gp_Pnt, gp_Pnt> vectors = make_tuple(gp_Pnt(), gp_Pnt());
switch (selectEles.at(1)->nType)
{
case ELE_LINE:
toolName = ToolTypeToString(ToolType::PointsInput);
PointF.insert(PointF.end(), selectEles.at(1)->PointF.begin(), selectEles.at(1)->PointF.end());
//使用最小二乘法确定线段的起点和终点
vectors = MathHelper::GetFitLine(listPoints);
mcs_Start = get<0>(vectors);
mcs_End = get<1>(vectors);
break;
default:
mcs_Start = selectEles.at(0)->GetMcsPosition();
mcs_End = selectEles.at(1)->GetMcsPosition();
PointF.push_back(selectEles.at(1)->GetMcsPosition());
break;
}
mcsPt = (mcs_Start.XYZ() + mcs_End.XYZ()) * 0.5;
mcs_Start = MathHelper::FindClosestPointOnPlane(myPlane,mcs_Start);
mcs_End = MathHelper::FindClosestPointOnPlane(myPlane, mcs_End);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
mcs_Start = FuncBase::ConvertToV2(myCoord, mcs_Start);
mcs_End = FuncBase::ConvertToV2(myCoord, mcs_End);
switch (myCoord->workingPlaneIdx)
{
case 0:
mcs_Start.SetZ(pcs_pt.Z());
mcs_End.SetZ(pcs_pt.Z());
break;
case 1:
mcs_Start.SetX(pcs_pt.X());
mcs_End.SetX(pcs_pt.X());
break;
case 2:
mcs_Start.SetY(pcs_pt.Y());
mcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
mcs_Start = FuncBase::ConvertPcsToMcs(myCoord, mcs_Start);
mcs_End = FuncBase::ConvertPcsToMcs(myCoord, mcs_End);
toolsInputs.push_back(ToolsInput{ toolName,selectEles.at(1)->m_strElementName, selectEles.at(1)->m_strElementUid });
m_pMCS->McsPosition = (mcs_Start.XYZ() + mcs_End.XYZ()) * 0.5f;
toolTypes[ToolType::AutomaticDecision] = toolsInputs;
IsUesedToolTypes[AutomaticDecision] = true;
}
else
{
bool retemp = LinePointsInput(selectEles, parentEle, toolsInputs, addPoints, AutomaticDecision, fitMethod);
if (!retemp)
{
exception ex;
throw ex;
}
}
if (myCloudLineIndexs.size() > 0)
{
for (int i = 0; i < myCloudLineIndexs.size(); i++)
{
selectEles->PointF.clear(); //清除云线的点集合
}
}
double dis = mcs_Start.Distance(mcs_End);
double length = dis;
if(selectEles.size() == 1)
length = (selectEles.at(0)->nType == ELE_LINE) ? ((EleLine*)selectEles.at(0))->Length : dis;
this->Length = length;
m_pMCS->McsPosition = (mcs_Start.XYZ() + mcs_End.XYZ()) * 0.5;
unordered_set<string> seen;
std::list<ToolsInput> deduped;
for (const auto& item : toolsInputs)
{
if (seen.insert(item.InputEleID).second) {
deduped.push_back(item);
}
}
toolsInputs.swap(deduped); // 替换回原 list
this->toolTypes[ToolType::AutomaticDecision] = toolsInputs;
this->IsUesedToolTypes[AutomaticDecision] = true;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
toolTypes[ToolType::AutomaticDecision] = toolsInputs;
IsUesedToolTypes[AutomaticDecision] = false;
return false;
}
}
/// <summary>
/// 垂直
/// </summary>
/// <param name="selectEle"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineVertical(CElementBase* selectEle, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
gp_Vec vec;
EleLine* line = nullptr;
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::Vertical),selectEle->m_strElementName, selectEle->m_strElementUid });
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
switch (selectEle->nType)
{
case ELE_GAP:
{
EleGap* gapline = (EleGap*)selectEle;
line = gapline->lineSegment1;
}
case ELE_DISTANCE:
case ELE_LINE:
{
if (line == nullptr)
line = (EleLine*)selectEle;
auto start_end = line->GetLineMcsStartEndPoint();
gp_Pnt mcs_Start = get<0>(start_end);
gp_Pnt mcs_End = get<1>(start_end);
this->Length = mcs_Start.Distance(mcs_End);
mcs_Start = MathHelper::FindClosestPointOnPlane(myPlane, mcs_Start);
mcs_End = MathHelper::FindClosestPointOnPlane(myPlane, mcs_End);
vec = gp_Vec(mcs_Start, mcs_End);
break;
}
case ElE_COORDINATION_SYSTME:
{
Alignment* sysCoord = (Alignment*)selectEle;
auto myVec = sysCoord->GetWPVec();
vec = std::get<0>(myVec);
this->Length = 10;
break;
}
default:
break;
}
vec = gp_Vec(-vec.Y(), vec.X(), vec.Z());
vec_Line = vec;
if (!this->m_pMCS->McsPosition.IsEqual(gp_Pnt(0, 0, 0), 1.0e-9))
{
this->mcs_Start = this->m_pMCS->McsPosition.XYZ() + (vec_Line * this->Length * 0.5f).XYZ();
this->mcs_End = this->m_pMCS->McsPosition.XYZ() - (vec_Line * this->Length * 0.5f).XYZ();
this->vec_Line = gp_Vec(0, 0, 0);
}
this->ParentUid = parentEle->m_strElementUid;
this->toolTypes[ToolType::Vertical] = toolsInputs;
this->IsUesedToolTypes[Vertical] = true;
return true;
}
catch (const std::exception& e)
{
std::ignore = e;
this->toolTypes[ToolType::Vertical] = toolsInputs;
this->IsUesedToolTypes[Vertical] = false;
return false;
}
}
/// <summary>
/// 平行
/// </summary>
/// <param name="selectEle"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineParalle(CElementBase* selectEle, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
gp_Vec vec;
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::Parallel),selectEle->m_strElementName, selectEle->m_strElementUid });
EleLine* line = nullptr;
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
switch (selectEle->nType)
{
case ELE_GAP:
{
EleGap* gapline = (EleGap*)selectEle;
line = gapline->lineSegment1;
}
case ELE_DISTANCE:
case ELE_LINE:
{
if (line == nullptr)
line = (EleLine*)selectEle;
auto start_end = line->GetLineMcsStartEndPoint();
gp_Pnt mcs_Start = get<0>(start_end);
gp_Pnt mcs_End = get<1>(start_end);
this->Length = mcs_Start.Distance(mcs_End);
mcs_Start = MathHelper::FindClosestPointOnPlane(myPlane, mcs_Start);
mcs_End = MathHelper::FindClosestPointOnPlane(myPlane, mcs_End);
vec = gp_Vec(mcs_Start, mcs_End);
break;
}
case ElE_COORDINATION_SYSTME:
{
Alignment* sysCoord = (Alignment*)selectEle;
auto myVec = sysCoord->GetWPVec();
vec = std::get<0>(myVec);
this->Length = 10;
break;
}
default:
break;
}
vec.Normalize();
vec_Line = vec;
if (!this->m_pMCS->McsPosition.IsEqual(gp_Pnt(0, 0, 0), 1.0e-9))
{
this->mcs_Start = this->m_pMCS->McsPosition.XYZ() + (vec_Line * this->Length * 0.5f).XYZ();
this->mcs_End = this->m_pMCS->McsPosition.XYZ() - (vec_Line * this->Length * 0.5f).XYZ();
this->vec_Line = gp_Vec(0, 0, 0);
}
this->ParentUid = parentEle->m_strElementUid;
this->toolTypes[ToolType::Parallel] = toolsInputs;
this->IsUesedToolTypes[Parallel] = true;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[ToolType::Parallel] = toolsInputs;
this->IsUesedToolTypes[Parallel] = false;
return false;
}
}
/// <summary>
/// 切线
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineTange(vector<CElementBase*> selectEles, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), selectEles.at(0)->m_strElementName, selectEles.at(0)->m_strElementUid });
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), selectEles.at(1)->m_strElementName, selectEles.at(1)->m_strElementUid });
bool isAllCircle = false;
if ((selectEles.at(0)->nType == ELE_CIRCLE && selectEles.at(1)->nType == ELE_CIRCLE) || (selectEles.at(0)->nType == ELE_ARC && selectEles.at(1)->nType == ELE_ARC))
isAllCircle = true;
//点圆切线
auto solutions = PointCircleTangenLine(this, selectEles.at(1), selectEles.at(0)->GetMcsPosition(), selectEles, parentEle, isAllCircle);
if (mySolutCallback && m_nSolutionIndex == -1)
mySolutCallback(solutions);
else
{
EleLine* ele_Line = (EleLine*)solutions.at(m_nSolutionIndex);
this->mcs_Start = ele_Line->mcs_Start;
this->mcs_End = ele_Line->mcs_End;
this->Length = ele_Line->Length;
this->m_pMCS->McsPosition = ele_Line->m_pMCS->McsPosition;
this->m_pPCS->PcsPosition = ele_Line->m_pPCS->PcsPosition;
this->m_elementOffset.BefMcsPoint = ele_Line->m_elementOffset.BefMcsPoint;
}
this->toolTypes[ToolType::TangentLine] = toolsInputs;
this->IsUesedToolTypes[TangentLine] = true;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[ToolType::TangentLine] = toolsInputs;
this->IsUesedToolTypes[TangentLine] = false;
return false;
}
}
/// <summary>
/// 多点输入
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LinePointsInput(vector<CElementBase*> selectEles, CElementBase* parentEle, list<ToolsInput>& toolsInputs, vector<gp_Pnt> addPoints, ToolType myType, int fitMethod)
{
try
{
this->PointF.clear();
vector< int> myCloudLineIndexs;
unordered_set<string> seen;
std::list<ToolsInput> deduped;
for (int i = 0; i < selectEles.size(); i++)
{
if (selectEles->nType == ELE_LINE || selectEles->nType == ELE_POINT_CLOUD || selectEles->nType ==ELE_OPEN_CLOUD_LINE|| selectEles->nType == ELE_CLOSE_CLOUD_LINE)
{
ToolsInput toolsInput = ToolsInput();
if (this->m_listComponentElements.size() > 0 && selectEles->nType != ELE_LINE)
{
ComponentEle* mySegement = nullptr;
selectEles->PointF.clear();
for (auto comPonent : this->m_listComponentElements)
{
if (comPonent->IsSegementCom)
mySegement = comPonent;
if (mySegement != nullptr && selectEles->m_strElementUid == mySegement->m_strComponentUid)
{
vector<gp_Pnt> mySePts = ((EleOpenCloudLine*)selectEles)->ExtractSegmentFromCloudPoints(mySegement->SegementPts.at(0), mySegement->SegementPts.at(1), mySegement->IsOtherEdge);
selectEles->PointF.insert(selectEles->PointF.end(), mySePts.begin(),
mySePts.end());
}
else
{
continue;
}
}
myCloudLineIndexs.push_back(i);
toolsInput.ToolName = ToolTypeToString(ToolType::SectionComposition);
}
else
{
toolsInput.ToolName = ToolTypeToString(ToolType::PointsInput);
}
toolsInput.InputEleName = selectEles->m_strElementName;
toolsInput.InputEleID = selectEles->m_strElementUid;
toolsInputs.push_back(toolsInput);
this->PointF.insert(this->PointF.end(), selectEles->PointF.begin(), selectEles->PointF.end());
}
else
{
ToolsInput toolsInput = ToolsInput();
toolsInput.ToolName = ToolTypeToString(ToolType::MidPointComposition);
toolsInput.InputEleName = selectEles->m_strElementName;
toolsInput.InputEleID = selectEles->m_strElementUid;
toolsInputs.push_back(toolsInput);
this->PointF.push_back(selectEles->GetMcsPosition());
}
}
this->PointF.insert(this->PointF.end(), addPoints.begin(), addPoints.end());
bool fitRet = FitLine(this->PointF, parentEle, this->mcs_Start, this->mcs_End, fitMethod);
if (fitRet && selectEles.size() > 0 && selectEles[0] != nullptr)
{
LogEleLinePointsInputFitIfSet(
selectEles[0]->m_strElementUid.c_str(),
(int)this->PointF.size(),
this->mcs_Start.X(), this->mcs_Start.Y(), this->mcs_Start.Z(),
this->mcs_End.X(), this->mcs_End.Y(), this->mcs_End.Z());
}
if (!fitRet)
{
for (const auto& item : toolsInputs)
{
if (seen.insert(item.InputEleID).second) {
deduped.push_back(item);
}
}
toolsInputs.swap(deduped); // 替换回原 list
this->toolTypes[myType] = toolsInputs;
this->IsUesedToolTypes[myType] = false;
return false;
}
if (myCloudLineIndexs.size() > 0)
{
for (int i = 0; i < myCloudLineIndexs.size(); i++)
{
selectEles->PointF.clear(); //清除云线的点集合
}
}
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5;
this->ParentUid = parentEle->m_strElementUid;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[myType] = toolsInputs;
this->IsUesedToolTypes[myType] = false;
return false;
}
}
bool EleLine::FitLine(vector<gp_Pnt> fitPoints, CElementBase* parentEle, gp_Pnt& startPt, gp_Pnt& endPt, int fitMethod)
{
if (fitPoints.size() < 2)
{
return false;
}
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pnt mcsPt;
vector<gp_Pnt> fitPts;
for (int i = 0; i < fitPoints.size(); i++)
{
mcsPt = mcsPt.XYZ() + fitPoints.XYZ();
gp_Pnt subPoint = MathHelper::FindClosestPointOnPlane(myPlane, fitPoints);
fitPts.push_back(subPoint);
}
mcsPt = mcsPt.XYZ() / static_cast<Standard_Real>(fitPoints.size());
// 端点与扫描一致:cv::fitLine + 拾取框 Line2Lseg,不用 GetFitLine 坐标轴极值
double height = GetCurPixelLength();
tuple<gp_Pnt, gp_Pnt> pairs = MathHelper::GetFitLineEndpoints_LS(fitPts, myCoord->workingPlaneIdx);
startPt= std::get<0>(pairs);
endPt = std::get<1>(pairs);
gp_Pnt pcs_Start = FuncBase::ConvertToV2(myCoord, startPt);
gp_Pnt pcs_End = FuncBase::ConvertToV2(myCoord, endPt);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
switch (myCoord->workingPlaneIdx)
{
case 0:
pcs_Start.SetZ(pcs_pt.Z());
pcs_End.SetZ(pcs_pt.Z());
break;
case 1:
pcs_Start.SetX(pcs_pt.X());
pcs_End.SetX(pcs_pt.X());
break;
case 2:
pcs_Start.SetY(pcs_pt.Y());
pcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
startPt= FuncBase::ConvertPcsToMcs(myCoord, pcs_Start);
endPt = FuncBase::ConvertPcsToMcs(myCoord, pcs_End);
auto lastPt = fitPoints.at(0);
double startDis = lastPt.Distance(startPt);
double lastDis = lastPt.Distance(endPt);
if (startDis > lastDis)
{
gp_Pnt tempPt = startPt;
startPt= endPt;
endPt = tempPt;
}
return true;
}
/// <summary>
/// 中点构成
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineMidPointComposition(vector<CElementBase*> selectEles, CElementBase* parentEle)
{
try
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
this->PointF.clear();
if (selectEles.size() == 1)
{
this->m_pMCS->McsPosition = selectEles.at(0)->GetMcsPosition();
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::MidPointComposition), selectEles.at(0)->m_strElementName,selectEles.at(0)->m_strElementUid,vector<gp_Pnt> { selectEles.at(0)->GetMcsPosition() } });
this->PointF.push_back(selectEles.at(0)->GetMcsPosition());
this->toolTypes[ToolType::MidPointComposition] = toolsInputs;
if (!vec_Line.IsEqual(gp_Vec(0, 0, 0), 1.0e-9, 1.0e-9))
{
this->mcs_Start = this->m_pMCS->McsPosition.XYZ() + (vec_Line * this->Length * 0.5f).XYZ();
this->mcs_End = this->m_pMCS->McsPosition.XYZ() - (vec_Line * this->Length * 0.5f).XYZ();
this->vec_Line = gp_Vec(0, 0, 0);
this->IsUesedToolTypes[MidPointComposition] = true;
}
else
{
this->IsUesedToolTypes[MidPointComposition] = false;
return false;
}
}
else if(selectEles.size() == 2)
{
CElementBase* element1 = selectEles.at(0);
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::MidPointComposition) ,element1->m_strElementName ,element1->m_strElementUid ,vector<gp_Pnt> { element1->GetMcsPosition() } });
CElementBase* element2 = selectEles.at(1);
//检查是否有垂直/平行构造
if (element2->nType == ELE_LINE || element2->nType == ELE_DISTANCE || element2->nType == ELE_GAP || element2->nType == ElE_COORDINATION_SYSTME)
{
auto verIt = IsUesedToolTypes.find(Vertical);
auto parIt = IsUesedToolTypes.find(Parallel);
if (verIt != IsUesedToolTypes.end())
return LineVertical(element2, parentEle);
else if (parIt != IsUesedToolTypes.end())
return LineParalle(element2, parentEle);
}
this->mcs_Start = element1->GetMcsPosition();
this->mcs_End = element2->GetMcsPosition();
auto lastEle = selectEles.at(selectEles.size() - 1);
gp_Pnt lastPt = lastEle->PointF.at(lastEle->PointF.size() - 1);
double startDis = lastPt.Distance(this->mcs_Start);
double lastDis = lastPt.Distance(this->mcs_End);
if (startDis < lastDis)
{
gp_Pnt tempPt = this->mcs_Start;
this->mcs_Start = this->mcs_End;
this->mcs_End = tempPt;
}
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
mcsPt = (mcs_Start.XYZ() + mcs_End.XYZ()) * 0.5;
mcs_Start = MathHelper::FindClosestPointOnPlane(myPlane, mcs_Start);
mcs_End = MathHelper::FindClosestPointOnPlane(myPlane, mcs_End);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
mcs_Start = FuncBase::ConvertToV2(myCoord, mcs_Start);
mcs_End = FuncBase::ConvertToV2(myCoord, mcs_End);
switch (myCoord->workingPlaneIdx)
{
case 0:
mcs_Start.SetZ(pcs_pt.Z());
mcs_End.SetZ(pcs_pt.Z());
break;
case 1:
mcs_Start.SetX(pcs_pt.X());
mcs_End.SetX(pcs_pt.X());
break;
case 2:
mcs_Start.SetY(pcs_pt.Y());
mcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
mcs_Start = FuncBase::ConvertPcsToMcs(myCoord, mcs_Start);
mcs_End = FuncBase::ConvertPcsToMcs(myCoord, mcs_End);
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5f;
this->Length = this->mcs_Start.Distance(this->mcs_End);
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::MidPointComposition) ,element2->m_strElementName ,element2->m_strElementUid ,vector<gp_Pnt> { element1->GetMcsPosition() } });
PointF.push_back(element1->m_pMCS->McsPosition);
PointF.push_back(element2->m_pMCS->McsPosition);
this->IsUesedToolTypes[MidPointComposition] = true;
}
else
{
LinePointsInput(selectEles, parentEle, toolsInputs, vector<gp_Pnt> {}, MidPointComposition, 0);
}
this->toolTypes[ToolType::MidPointComposition] = toolsInputs;
this->IsUesedToolTypes[MidPointComposition] = true;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->IsUesedToolTypes[MidPointComposition] = false;
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
return false;
}
}
/// <summary>
/// 交叉
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineCorss(vector<CElementBase*> selectEles, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
ToolsInput toolsInput1 = ToolsInput();
toolsInput1.ToolName = ToolTypeToString(ToolType::Cross);
toolsInput1.InputEleName = selectEles.at(0)->m_strElementName;
toolsInput1.InputEleID = selectEles.at(0)->m_strElementUid;
toolsInputs.push_back(toolsInput1);
ToolsInput toolsInput2 = ToolsInput();
toolsInput2.ToolName = ToolTypeToString(ToolType::Cross);
toolsInput2.InputEleName = selectEles.at(1)->m_strElementName;
toolsInput2.InputEleID = selectEles.at(1)->m_strElementUid;
toolsInputs.push_back(toolsInput2);
this->toolTypes[ToolType::Cross] = toolsInputs;
CElementBase* element1 = selectEles.at(0);
CElementBase* element2 = selectEles.at(1);
if (element1->nType == ELE_PLANE && element2->nType == ELE_PLANE) //面面交叉
{
auto pairs = GetPlansCrossLine(element1, element2);
gp_Pnt startPo = std::get<0>(pairs);
gp_Pnt endPo = std::get<1>(pairs);
if (startPo.IsEqual(endPo, 1e-6))
return false;
this->mcs_Start = startPo;
this->mcs_End = endPo;
double z = (this->mcs_Start.Z() + this->mcs_End.Z()) * 0.5;
this->mcs_Start.SetZ(z);
this->mcs_End.SetZ(z);
this->Length = this->mcs_Start.Distance(this->mcs_End);
}
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5;
this->ParentUid = parentEle->m_strElementUid;
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
this->IsUesedToolTypes[Cross] = true;
this->ConSubPoints.clear();
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[ToolType::Cross] = toolsInputs;
this->IsUesedToolTypes[Cross] = false;
return false;
}
}
/// <summary>
/// 平分线
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
bool EleLine::LineBisector(vector<CElementBase*> selectEles, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
ToolsInput toolsInput1 = ToolsInput();
toolsInput1.ToolName = ToolTypeToString(ToolType::Bisector);
toolsInput1.InputEleName = selectEles.at(0)->m_strElementName;
toolsInput1.InputEleID = selectEles.at(0)->m_strElementUid;
toolsInputs.push_back(toolsInput1);
ToolsInput toolsInput2 = ToolsInput();
toolsInput2.ToolName = ToolTypeToString(ToolType::Bisector);
toolsInput2.InputEleName = selectEles.at(1)->m_strElementName;
toolsInput2.InputEleID = selectEles.at(1)->m_strElementUid;
toolsInputs.push_back(toolsInput2);
this->toolTypes[ToolType::Bisector] = toolsInputs;
CElementBase* element1 = selectEles.at(0);
CElementBase* element2 = selectEles.at(1);
CElementBase* lineSegment1;
bool isLine1 = FuncBase::GetLineSegment(element1, &lineSegment1);
CElementBase* lineSegment2;
bool isLine2 = FuncBase::GetLineSegment(element2, &lineSegment2);
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
// 线线平分
if (isLine1 && isLine2)
{
vector<CElementBase> elements = vector<CElementBase>();
EleLine* line1 = (EleLine*)lineSegment1;
EleLine* line2 = (EleLine*)lineSegment2;
auto start_end1 = line1->GetLineMcsStartEndPoint();
gp_Pnt line1_mcsStart = get<0>(start_end1);
gp_Pnt line1_mcsEnd = get<1>(start_end1);
auto start_end2 = line2->GetLineMcsStartEndPoint();
gp_Pnt line2_mcsStart = get<0>(start_end2);
gp_Pnt line2_mcsEnd = get<1>(start_end2);
mcsPt = (line1->m_pMCS->McsPosition.XYZ() + line2->m_pMCS->McsPosition.XYZ()) * 0.5;
line1_mcsStart = MathHelper::FindClosestPointOnPlane(myPlane, line1_mcsStart);
line1_mcsEnd = MathHelper::FindClosestPointOnPlane(myPlane, line1_mcsEnd);
line2_mcsStart = MathHelper::FindClosestPointOnPlane(myPlane, line2_mcsStart);
line2_mcsEnd = MathHelper::FindClosestPointOnPlane(myPlane, line2_mcsEnd);
auto result = MathHelper::CalculateBisectorAndTangent(line1_mcsStart, line1_mcsEnd, line2_mcsStart, line2_mcsEnd);
gp_Pnt midpt1 = (line1_mcsStart.XYZ() + line1_mcsEnd.XYZ()) * 0.5;
gp_Pnt midpt2 = (line2_mcsStart.XYZ() + line2_mcsEnd.XYZ()) * 0.5;
BRepAlgoAPI_Section intersection1(BRepBuilderAPI_MakeEdge(midpt1, midpt2),
BRepBuilderAPI_MakeEdge(std::get<0>(result.at(0)), std::get<1>(result.at(0))).Edge());
BRepAlgoAPI_Section intersection2(BRepBuilderAPI_MakeEdge(midpt1, midpt2),
BRepBuilderAPI_MakeEdge(std::get<0>(result.at(1)), std::get<1>(result.at(1))).Edge());
// 输出交点结果
TopoDS_Shape resultshape1 = intersection1.Shape();
TopoDS_Shape resultshape2 = intersection2.Shape();
if (resultshape1.IsNull() || resultshape2.IsNull()) {
return false;
}
else
{
if (!resultshape2.IsNull())
{
auto tempresult = result;
result.clear();
result.push_back(tempresult.at(1));
result.push_back(tempresult.at(0));
}
}
vector<pair<gp_Pnt, gp_Pnt>> conResult;
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
for (auto myPair : result)
{
gp_Pnt pcs_Start = FuncBase::ConvertToV2(myCoord, std::get<0>(myPair));
gp_Pnt pcs_End = FuncBase::ConvertToV2(myCoord, std::get<1>(myPair));
switch (myCoord->workingPlaneIdx)
{
case 0:
pcs_Start.SetZ(pcs_pt.Z());
pcs_End.SetZ(pcs_pt.Z());
break;
case 1:
pcs_Start.SetX(pcs_pt.X());
pcs_End.SetX(pcs_pt.X());
break;
case 2:
pcs_Start.SetY(pcs_pt.Y());
pcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
conResult.push_back({ FuncBase::ConvertPcsToMcs(myCoord, pcs_Start),FuncBase::ConvertPcsToMcs(myCoord, pcs_End) });
}
auto solutions = DealWithLineBisector(conResult, selectEles, parentEle);
switch (m_nSolutionIndex)
{
case -1:
if (mySolutCallback)
mySolutCallback(solutions);
break;
case 0:
this->mcs_Start = ((EleLine*)solutions.at(0))->mcs_Start;
this->mcs_End = ((EleLine*)solutions.at(0))->mcs_End;
break;
case 1:
this->mcs_Start = ((EleLine*)solutions.at(1))->mcs_Start;
this->mcs_End = ((EleLine*)solutions.at(1))->mcs_End;
break;
default:
break;
}
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5f;;
this->Length = this->mcs_Start.Distance(this->mcs_End);
}
// 线和非线特征平分
if (!isLine1 && isLine2 || isLine1 && !isLine2)
{
auto NoLeelement = !isLine1 ? element1 : element2;
auto Lelement = isLine1 ? (EleLine*)lineSegment1 : (EleLine*)lineSegment2;
auto LelementStart_end = Lelement->GetLineMcsStartEndPoint();
gp_Pnt line_mcsStart = get<0>(LelementStart_end);
gp_Pnt line_mcsEnd = get<1>(LelementStart_end);
gp_Pnt centerNoLPo = NoLeelement->GetMcsPosition();
gp_Pnt centerLPo = Lelement->GetMcsPosition();
mcsPt = (centerNoLPo.XYZ() + centerLPo.XYZ()) * 0.5;
this->Length = Lelement->Length;
this->m_pMCS->McsPosition = (centerNoLPo.XYZ() + centerLPo.XYZ()) * 0.5f;
line_mcsStart = MathHelper::FindClosestPointOnPlane(myPlane, line_mcsStart);
line_mcsEnd = MathHelper::FindClosestPointOnPlane(myPlane, line_mcsEnd);
// 计算线段的方向向量算出平分线的中心点偏移
gp_Vec direction = gp_Vec(line_mcsStart, line_mcsEnd);
direction.Normalize();
double distance = this->Length * 0.5f;
this->mcs_Start = this->m_pMCS->McsPosition.XYZ() + (direction * distance).XYZ();
this->mcs_End = this->m_pMCS->McsPosition.XYZ() - (direction * distance).XYZ();
gp_Pnt pcs_Start = FuncBase::ConvertToV2(myCoord, this->mcs_Start);
gp_Pnt pcs_End = FuncBase::ConvertToV2(myCoord, this->mcs_End);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
switch (myCoord->workingPlaneIdx)
{
case 0:
pcs_Start.SetZ(pcs_pt.Z());
pcs_End.SetZ(pcs_pt.Z());
break;
case 1:
pcs_Start.SetX(pcs_pt.X());
pcs_End.SetX(pcs_pt.X());
break;
case 2:
pcs_Start.SetY(pcs_pt.Y());
pcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
this->mcs_Start = FuncBase::ConvertPcsToMcs(myCoord, pcs_Start);
this->mcs_End = FuncBase::ConvertPcsToMcs(myCoord, pcs_End);
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5;
}
// 非线特征平分线
if (!isLine1 && !isLine2)
{
auto element1CenterPo = element1->GetMcsPosition();
auto element2CenterPo = element2->GetMcsPosition();
mcsPt = (element1CenterPo.XYZ() + element2CenterPo.XYZ()) * 0.5;
// 两个中心点间的距离
this->Length = element1CenterPo.Distance(element2CenterPo);
double distance = (double)this->Length * 0.5f;
// 宽度需重新设置这里默认1
element1CenterPo = MathHelper::FindClosestPointOnPlane(myPlane, element1CenterPo);
element2CenterPo = MathHelper::FindClosestPointOnPlane(myPlane, element2CenterPo);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
element1CenterPo = FuncBase::ConvertToV2(myCoord, element1CenterPo);
element2CenterPo = FuncBase::ConvertToV2(myCoord, element2CenterPo);
switch (myCoord->workingPlaneIdx)
{
case 0:
element1CenterPo.SetZ(pcs_pt.Z());
element2CenterPo.SetZ(pcs_pt.Z());
break;
case 1:
element1CenterPo.SetX(pcs_pt.X());
element2CenterPo.SetX(pcs_pt.X());
break;
case 2:
element1CenterPo.SetY(pcs_pt.Y());
element2CenterPo.SetY(pcs_pt.Y());
break;
default:
break;
}
element1CenterPo = FuncBase::ConvertPcsToMcs(myCoord, element1CenterPo);
element2CenterPo = FuncBase::ConvertPcsToMcs(myCoord, element2CenterPo);
this->m_pMCS->McsPosition = (element1CenterPo.XYZ() + element2CenterPo.XYZ()) * 0.5;
// 两个中心点的方向向量
gp_Vec direction = gp_Vec(element1CenterPo, element2CenterPo);
// 与两个中心点垂直的方向向量也就是平分线的向量
gp_Vec normal = gp_Vec(-direction.Y(), direction.X(), direction.Z());
normal.Normalize();
// 向量归一化处理
gp_Pnt lineSegmentSatrtPo = this->m_pMCS->McsPosition.XYZ() + (normal * distance).XYZ();
gp_Pnt lineSegmentEndPo = this->m_pMCS->McsPosition.XYZ() - (normal * distance).XYZ();
this->mcs_Start = lineSegmentSatrtPo;
this->mcs_End = lineSegmentEndPo;
}
this->ParentUid = parentEle->m_strElementUid;
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
this->IsUesedToolTypes[Bisector] = true;
this->ConSubPoints.clear();
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[ToolType::Bisector] = toolsInputs;
this->IsUesedToolTypes[Bisector] = false;
return false;
}
}
/// <summary>
/// 处理线的平分
/// </summary>
/// <param name="resultLinePair"></param>
/// <param name="seletEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
vector<CElementBase*> EleLine::DealWithLineBisector(vector<pair<gp_Pnt, gp_Pnt>> resultLinePair, vector<CElementBase*> seletEles, CElementBase* parentEle)
{
vector<CElementBase*> elements = vector<CElementBase*>();
for (auto line : resultLinePair)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
EleLine* elementLine = (EleLine*)((EleLine*)this)->Clone();
elementLine->ParentUid = parentEle->m_strElementUid;
elementLine->mcs_Start = line.first;
elementLine->mcs_End = line.second;
elementLine->Length = elementLine->mcs_Start.Distance(elementLine->mcs_End);
elementLine->m_pMCS->McsPosition = (elementLine->mcs_Start.XYZ() + elementLine->mcs_End.XYZ()) * 0.5f;
elementLine->Tag = Special;
elementLine->solution_Tag = "BISECTOR";
elementLine->m_pPCS->PcsPosition = FuncBase::ConvertToV2(parentEle, elementLine->m_pMCS->McsPosition);
elementLine->m_elementOffset.BefMcsPoint = elementLine->m_pPCS->PcsPosition;
elementLine->m_strElementUid = MathHelper::GenerateGuid();
elementLine->IsUesedToolTypes[TangentLine] = true;
elements.push_back(elementLine);
}
elements.at(0)->solutionSubTag = SOLUTIONSUBTYPE::MID;
elements.at(1)->solutionSubTag = SOLUTIONSUBTYPE::SUPPER;
elements.at(0)->m_nSolutionIndex = 0;
elements.at(1)->m_nSolutionIndex = 1;
elements.push_back(seletEles.at(0));
elements.push_back(seletEles.at(1));
return elements;
}
tuple<gp_Pnt, gp_Pnt> EleLine::GetPlansCrossLine(CElementBase* ele1, CElementBase* ele2)
{
ElePlane* plane1 = ((ElePlane*)ele1);
ElePlane* plane2 = ((ElePlane*)ele2);
TopoDS_Face face1 = CreateFace(plane1);
TopoDS_Face face2 = CreateFace(plane2);
// 计算面面交线
BRepAlgoAPI_Section section(face1, face2);
section.Build(); // 必须调用Build()生成结果
if (!section.IsDone()) {
// 错误处理:交线不存在或计算失败
return { gp_Pnt(0,0,0),gp_Pnt(0,0,0) };
}
// 提取交线结果
const TopoDS_Shape& result = section.Shape();
// 遍历结果中的边(Edge)
TopExp_Explorer explorer(result, TopAbs_EDGE);
vector<gp_Pnt> listPoints = vector<gp_Pnt>();
for (; explorer.More(); explorer.Next()) {
const TopoDS_Edge& edge = TopoDS::Edge(explorer.Current());
// 获取边的几何曲线
Standard_Real start, end;
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, start, end);
// 如果是直线(两平面交线为直线)
if (curve->DynamicType() == STANDARD_TYPE(Geom_Line)) {
Handle(Geom_Line) line = Handle(Geom_Line)::DownCast(curve);
//取点和直线的交点
for (gp_Pnt po : plane1->pointsCorners)
{
//点与直线做垂线,得出拟合直线的交点
gp_Pnt intersectionP = MathHelper::projectPointOntoLine(po, line->Lin());
listPoints.push_back(intersectionP);
}
for (gp_Pnt po : plane2->pointsCorners)
{
//点与直线做垂线,得出拟合直线的交点
gp_Pnt intersectionP = MathHelper::projectPointOntoLine(po, line->Lin());
listPoints.push_back(intersectionP);
}
tuple<gp_Pnt, gp_Pnt> pairs = MathHelper::GetFitLine(listPoints);
return pairs;
}
else
{
return { gp_Pnt(0,0,0),gp_Pnt(0,0,0) };
}
}
return { gp_Pnt(0,0,0),gp_Pnt(0,0,0) };
}
TopoDS_Face EleLine::CreateFace(CElementBase* ele1)
{
ElePlane* plane = ((ElePlane*)ele1);
BRepBuilderAPI_MakeEdge edge1(plane->pointsCorners.at(0), plane->pointsCorners.at(1));
BRepBuilderAPI_MakeEdge edge2(plane->pointsCorners.at(1), plane->pointsCorners.at(2));
BRepBuilderAPI_MakeEdge edge3(plane->pointsCorners.at(2), plane->pointsCorners.at(3));
BRepBuilderAPI_MakeEdge edge4(plane->pointsCorners.at(3), plane->pointsCorners.at(0));
// 将边创建成一个线框(Wire)
BRepBuilderAPI_MakeWire wire;
wire.Add(edge1.Edge());
wire.Add(edge2.Edge());
wire.Add(edge3.Edge());
wire.Add(edge4.Edge());
// 创建面
BRepBuilderAPI_MakeFace makeFace(wire.Wire());
TopoDS_Face face = makeFace.Face();
return face;
}
tuple<gp_Pnt, gp_Pnt> EleLine::GetLineMcsStartEndPoint()
{
gp_Pnt lineStart = this->mcs_Start;
gp_Pnt lineEnd = this->mcs_End;
if (this->m_elementOffset.m_bIsOffseted)
{
lineStart = FuncBase::GetMatrixPoint(this, this->mcs_Start);
lineEnd = FuncBase::GetMatrixPoint(this, this->mcs_End);
}
return make_tuple(lineStart, lineEnd);
}
/// <summary>
/// 最小范围
/// </summary>
/// <param name="selectEles"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::LineMinimunRange(vector<CElementBase*> selectEles, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
try
{
vector<gp_Pnt> points = vector<gp_Pnt>();
for (CElementBase* element : selectEles)
{
if (element->nType == ELE_LINE || element->nType == ELE_OPEN_CLOUD_LINE ||
element->nType == ELE_POINT_CLOUD)
{
// Insert all features from points1 into PointF
this->PointF.insert(PointF.end(), element->PointF.begin(), element->PointF.end());
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::RingZone),element->m_strElementName,element->m_strElementUid });
points.insert(points.end(), element->PointF.begin(), element->PointF.end());
}
else
{
points.push_back(element->GetMcsPosition());
this->PointF.push_back(element->GetMcsPosition());
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::RingZone),element->m_strElementName,element->m_strElementUid });
}
}
tuple<gp_Pnt, gp_Pnt> vectors = tuple<gp_Pnt, gp_Pnt>{ points.at(0), points.at(1) };
if (points.size() > 2)
{
// 进行切比雪夫拟合直线
vectors = MathHelper::FitLineToPointCloud(points);
}
gp_Pnt startPoint = std::get<0>(vectors);
gp_Pnt endPoint = std::get<1>(vectors);
this->mcs_Start = startPoint;
this->mcs_End = endPoint;
double z = (this->mcs_Start.Z() + this->mcs_End.Z()) * 0.5;
this->mcs_Start.SetZ(z);
this->mcs_End.SetZ(z);
this->m_pMCS->McsPosition = (this->mcs_Start.XYZ() + this->mcs_End.XYZ()) * 0.5f;
this->Length = this->mcs_Start.Distance(this->mcs_End);
this->m_pPCS->PcsPosition = FuncBase::ConvertToV2(parentEle, this->m_pMCS->McsPosition);
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
this->toolTypes[ToolType::MinimumRange] = toolsInputs;
this->IsUesedToolTypes[MinimumRange] = true;
return true;
}
catch (const std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
this->toolTypes[ToolType::MinimumRange] = toolsInputs;
this->IsUesedToolTypes[MinimumRange] = false;
this->m_pPCS->PcsPosition = FuncBase::ConvertToV2(parentEle, this->m_pMCS->McsPosition);
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
return false;
}
}
/// <summary>
/// 呼出
/// </summary>
/// <param name="selectEle"></param>
/// <param name="parentEle"></param>
/// <returns></returns>
bool EleLine::CallOutLine(CElementBase* selectEle, CElementBase* parentEle)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
if (selectEle->nType == ELE_LINE)
{
EleLine* element = (EleLine*)(selectEle);
this->m_pMCS->McsPosition = element->GetMcsPosition();
auto start_end = element->GetLineMcsStartEndPoint();
gp_Pnt line_mcsStart = get<0>(start_end);
gp_Pnt line_mcsEnd = get<1>(start_end);
this->mcs_Start = line_mcsStart;
this->mcs_End = line_mcsEnd;
this->Length = mcs_Start.Distance(mcs_End);
this->vec_Line = element->vec_Line;
this->PointF = element->GetPointF();
this->ParentUid = parentEle->m_strElementUid;
this->m_pPCS->PcsPosition = FuncBase::ConvertToV2(parentEle, this->m_pMCS->McsPosition);
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::PointsInput) ,selectEle->m_strElementName,selectEle->m_strElementUid });
this->toolTypes[ToolType::callOut] = toolsInputs;
this->IsUesedToolTypes[callOut] = true;
return true;
}
else
{
this->m_pPCS->PcsPosition = FuncBase::ConvertToV2(parentEle, this->m_pMCS->McsPosition);
this->m_elementOffset.BefMcsPoint = this->m_pMCS->McsPosition;
this->toolTypes[ToolType::callOut] = toolsInputs;
this->IsUesedToolTypes[callOut] = false;
return false;
}
}
vector<gp_Pnt> EleLine::readPointsFromFile(std::string filename) {
std::vector<gp_Pnt> points;
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error opening file: " << filename << std::endl;
return points;
}
std::string line;
while (std::getline(file, line)) {
// 查找x和y的位置
size_t x_pos = line.find("x=");
size_t y_pos = line.find("y=");
if (x_pos != std::string::npos && y_pos != std::string::npos)
{
// 提取x值
std::string x_str = line.substr(x_pos + 2);
x_str = x_str.substr(0, x_str.find(' '));
// 提取y值
std::string y_str = line.substr(y_pos + 2);
y_str = y_str.substr(0, y_str.find(' '));
try {
double x = std::stod(x_str);
double y = std::stod(y_str);
points.emplace_back(x, y, 0.0); // z坐标设为0
}
catch (const std::exception& e)
{
std::cerr << "Exception caught: " << e.what() << std::endl;
std::cerr << "Error parsing line: " << line << std::endl;
}
}
}
file.close();
return points;
}
/// <summary>
/// 选择点圆/弧/椭圆的切线
/// </summary>
/// <param name="element">要构造的特征</param>
/// <param name="inputElement">圆/弧/椭圆</param>
/// <param name="point">点</param>
/// <param name="inputElements">特征列表</param>
/// <param name="parentEle">父特征</param>
/// <param name="isTowCircle">是否是圆圆</param>
vector<CElementBase*> EleLine::PointCircleTangenLine(CElementBase* element, CElementBase* inputElement, const gp_Pnt& point, vector<CElementBase*> inputElements, CElementBase* parentEle, bool isTowCircle)
{
gp_Pnt point1;
gp_Pnt point2;
if (inputElements[0]->GetMcsPosition().IsEqual(inputElements.at(1)->GetMcsPosition(), 1e-6))
return vector<CElementBase*>();
vector<pair<gp_Pnt, gp_Pnt>> dicLines = vector<pair<gp_Pnt, gp_Pnt>>();
if (isTowCircle)//圆圆切线
{
double radius1 = FuncBase::GetRadius(inputElements.at(0));
double radius2 = FuncBase::GetRadius(inputElements.at(1));
dicLines = MathHelper::CalculateTangentLineCircle(inputElements[0]->GetMcsPosition(), radius1, inputElements.at(1)->GetMcsPosition(), radius2);
}
else
{
//点圆切线
double radius = FuncBase::GetRadius(inputElement);
dicLines = MathHelper::CalculateTangents(inputElement->GetMcsPosition(), radius, point, point1, point2);
if (inputElement->nType == ELE_ELLIPSE)
{
auto ellipse = (EleEllipse*)inputElement;
dicLines = MathHelper::CalculateTangent_Ellipse(ellipse->GetMcsPosition(), 2 * (double)ellipse->maxjorAxis, 2 * (double)ellipse->minorAxis
, ellipse->rotateAngle, point, point1, point2);
}
}
((EleLine*)element)->mcs_Start = point1;
((EleLine*)element)->mcs_End = point2;
((EleLine*)element)->m_pMCS->McsPosition = (((EleLine*)element)->mcs_Start.XYZ() + ((EleLine*)element)->mcs_End.XYZ()) * 0.5f;
if (dicLines.size() == 0)
return vector<CElementBase*>();
vector<CElementBase*> elements = vector<CElementBase*>();
int index = 0;
Alignment* myCoord = ((Alignment*)parentEle);
gp_Pln myPlane = FuncBase::GetWorkingPlane(parentEle);
gp_Pnt mcsPt;
for (auto line : dicLines)
{
list<ToolsInput> toolsInputs = list<ToolsInput>();
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), inputElements.at(0)->m_strElementName, inputElements.at(0)->m_strElementUid });
toolsInputs.push_back(ToolsInput{ ToolTypeToString(ToolType::TangentLine), inputElements.at(1)->m_strElementName, inputElements.at(1)->m_strElementUid });
EleLine* elementLine = (EleLine*)((EleLine*)element)->Clone();
elementLine->ParentUid = parentEle->m_strElementUid;
elementLine->mcs_Start = line.first;
elementLine->mcs_End = line.second;
mcsPt = (elementLine->mcs_Start.XYZ() + elementLine->mcs_End.XYZ()) * 0.5;
elementLine->mcs_Start = MathHelper::FindClosestPointOnPlane(myPlane, elementLine->mcs_Start);
elementLine->mcs_End = MathHelper::FindClosestPointOnPlane(myPlane, elementLine->mcs_End);
gp_Pnt pcs_pt = FuncBase::ConvertToV2(myCoord, mcsPt);
elementLine->mcs_Start = FuncBase::ConvertToV2(myCoord, elementLine->mcs_Start);
elementLine->mcs_End = FuncBase::ConvertToV2(myCoord, elementLine->mcs_End);
switch (myCoord->workingPlaneIdx)
{
case 0:
elementLine->mcs_Start.SetZ(pcs_pt.Z());
elementLine->mcs_End.SetZ(pcs_pt.Z());
break;
case 1:
elementLine->mcs_Start.SetX(pcs_pt.X());
elementLine->mcs_End.SetX(pcs_pt.X());
break;
case 2:
elementLine->mcs_Start.SetY(pcs_pt.Y());
elementLine->mcs_End.SetY(pcs_pt.Y());
break;
default:
break;
}
elementLine->mcs_Start = FuncBase::ConvertPcsToMcs(myCoord, elementLine->mcs_Start);
elementLine->mcs_End = FuncBase::ConvertPcsToMcs(myCoord, elementLine->mcs_End);
elementLine->Length = elementLine->mcs_Start.Distance(elementLine->mcs_End);
elementLine->m_pMCS->McsPosition = (elementLine->mcs_Start.XYZ() + elementLine->mcs_End.XYZ()) * 0.5f;
elementLine->Tag = Special;
elementLine->m_elementOffset.BefMcsPoint = elementLine->m_pPCS->PcsPosition;
elementLine->m_strElementUid = MathHelper::GenerateGuid();
elementLine->toolTypes[ToolType::TangentLine] = toolsInputs;
elementLine->IsUesedToolTypes[TangentLine] = true;
elementLine->m_nSolutionIndex = index++;
elements.push_back(elementLine);
}
elements.push_back(inputElements.at(0));
elements.push_back(inputElements.at(1));
return elements;
}
GeomAdaptor_Curve EleLine::GetCurve()
{
GeomAdaptor_Curve adaptorCurve;
gp_Pnt startP = this->mcs_Start;
gp_Pnt endP = this->mcs_End;
if (startP.XYZ().IsEqual(endP.XYZ(), 1.0e-9))
return adaptorCurve;
//处理特征偏移
auto points = FuncBase::ElementOffset(this);
if (points.size() > 0)
{
startP = points[0];
endP = points[1];
}
gp_Vec myVec(startP, endP);
gp_Ax1 gpax(startP, myVec);
Handle_Geom_Line theLine = new Geom_Line(gpax);
adaptorCurve = GeomAdaptor_Curve(theLine);
return adaptorCurve;
}
|
|