码迷,mamicode.com
首页 > 其他好文 > 详细

获得轮廓上距离鼠标最近的点

时间:2021-04-28 12:16:52      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:infinite   ble   ==   key   VID   standard   extc   red   builder   

技术图片

 

 

 

想用鼠标在线条(TopoDS_Edge/TopoDS_Wire)、面(TopoDS_Face)或任意形状(TopoDS_Shape)上,随机选择一个点,需要先将鼠标屏幕坐标转为模型空间坐标,然后计算空间坐标到模型的最近点。

当模型较为复杂或网格模型,速度会有所降低。

第一步:坐标转换

Handle(V3d_View) view3d = ...;

V3d_Coordinate XEye,YEye,ZEye,XAt,YAt,ZAt; view3d
->Eye(XEye,YEye,ZEye); view3d->At(XAt,YAt,ZAt); gp_Pnt EyePoint(XEye,YEye,ZEye); gp_Pnt AtPoint(XAt,YAt,ZAt); gp_Vec EyeVector(EyePoint,AtPoint); gp_Dir EyeDir(EyeVector); Standard_Real x, y, z; view3d->Convert(scP.x, scP.y, x, y, z); gp_Pnt tempPnt(x, y, z);

TopoDS_Wire sh = ...;

gp_Pnt aPnt;

  gp_Dir aDir;


pickNearestPoint(tempPnt,EyeDir, Sh, aPnt,aDir,TopAbs_EDGE);

第二步:计算最近点


Standard_Real DistanceOut(const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
Bnd_Box BBox1, BBox2;
BRepBndLib::Add(S1, BBox1);
BRepBndLib::Add(S2, BBox2);
return BBox1.Distance(BBox2);
}

Standard_Real DistanceIn(const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
Bnd_Box LBBox, SBBox;
BRepBndLib::Add(S1, SBBox);
BRepBndLib::Add(S2, LBBox);

Standard_Real LXmin, LYmin, LZmin, LXmax, LYmax, LZmax,
SXmin, SYmin, SZmin, SXmax, SYmax, SZmax;
SBBox.Get(SXmin, SYmin, SZmin,
SXmax, SYmax, SZmax);
LBBox.Get(LXmin, LYmin, LZmin,
LXmax, LYmax, LZmax);

//Compute the max distance between input shapes------------//
gp_XYZ Lmin(LXmin, LYmin, LZmin),
Lmax(LXmax, LYmax, LZmax);
gp_XYZ Smin(SXmin, SYmin, SZmin),
Smax(SXmax, SYmax, SZmax);
Lmax.Subtract(Lmin);
Smax.Subtract(Smin);
return Lmax.Modulus() + Smax.Modulus() + DistanceOut(S1, S2);
}


bool
pickNearestPoint(const gp_Pnt& P, const gp_Dir& viewDir, const TopoDS_Shape &S, gp_Pnt& relPoint, gp_Dir& faceNormal,bool onlyEdges) { if (S.IsNull()) return false; if (onlyEdges) { TopTools_IndexedMapOfShape M; TopExp::MapShapes(S, TopAbs_EDGE, M); int count = M.Extent(); if (count == 0) return false; gp_Pnt tempProjPnt; gp_Dir tempProjPntFaceNormal; double maxDis = Precision::Infinite(), dis; bool isOk = false; for (int i = 1; i <= count; i++) { const TopoDS_Edge &E = TopoDS::Edge(M.FindKey(i)); if (pickNearestPoint(P,viewDir,E, tempProjPnt, tempProjPntFaceNormal,false)) { dis = tempProjPnt.Distance(P); if (dis < maxDis) { maxDis = dis; relPoint = tempProjPnt; } isOk = true; } } return isOk; } else { double d = DistanceIn(BRepBuilderAPI_MakeVertex(P), S); gp_Vec Vsup(viewDir.XYZ() * 2 * d); TopoDS_Edge tempEdge = BRepBuilderAPI_MakeEdge(P.Translated(-1 * Vsup), P.Translated(Vsup)/*EyePoint*/); bool ok = false; //速度快 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { if (S.ShapeType() == TopAbs_EDGE) { BRepExtrema_ExtCC ext(tempEdge, TopoDS::Edge(S)); if (ext.IsDone() && ext.NbExt() > 0) { //get min distance double distance = Precision::Infinite(); for (int i = 1; i <= ext.NbExt(); i++) { Standard_Real d = ext.SquareDistance(i); if (d < distance) { relPoint = ext.PointOnE2(i); distance = d; ok = true; } } } } }
}
return true;
}

更多精彩请关注公众号


技术图片

 

 

获得轮廓上距离鼠标最近的点

标签:infinite   ble   ==   key   VID   standard   extc   red   builder   

原文地址:https://www.cnblogs.com/occi/p/14711707.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!