找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3305|回复: 19

[每日一码] 射线法判断点是否在曲线内

[复制链接]

已领礼包: 13个

财富等级: 恭喜发财

发表于 2017-8-12 00:23:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
判断点是否在曲线内,可以用REGION的方法,但是更快的是用射线法,下面是实现代码

[C++] 纯文本查看 复制代码
enum IncidenceType
{
           kIncidenceToLeft = 0,
           kIncidenceToRight,
           kIncidenceToFront,
           kIncidenceUnknown
};
 
IncidenceType CurveIncidence(const AcDbCurve* pCurve,
                                       const double& param,
                                       const AcGeVector3d& dir,
                                       const AcGeVector3d& normal)
{
           AcGeVector3d deriv1;
           pCurve->getFirstDeriv(param, deriv1);
 
           if(deriv1.isParallelTo(dir))
           {
                      // need second degree analysis
                      AcGeVector3d deriv2;
                      pCurve->getSecondDeriv(param, deriv2);
 
                      if(deriv2.isZeroLength() || deriv2.isParallelTo(dir))
                                  return kIncidenceToFront;
                      else
                      {
                                  if(deriv2.crossProduct(dir).dotProduct(normal) < 0)
                                             return kIncidenceToRight;
                                 
                                  else
                                             return kIncidenceToLeft;
                      }
           }
 
           if(deriv1.crossProduct(dir).dotProduct(normal) < 0)
                      return kIncidenceToLeft;
           else
                      return kIncidenceToRight;
}
 
Acad::ErrorStatus IsInsideCurve(const AcDbCurve* pCurve,
                                             const AcGePoint3d& testPt,
                                             bool& result)
{
           result = false;
 
           if(!pCurve->isClosed() || !pCurve)
           {
                      //Curve needs to be closed
                      return Acad::eInvalidInput;
           }
 
           Acad::ErrorStatus es;
           AcDb2dPolyline*p2dPoly = AcDb2dPolyline::cast(pCurve);
 
           if(p2dPoly != NULL && p2dPoly->polyType() != AcDb::k2dSimplePoly)
           {
                      // Not supported
                      return Acad::eInvalidInput;
           }
 
           AcGePoint3d ptOnCurve;
           es = pCurve->getClosestPointTo(testPt, ptOnCurve);
          
           if(testPt.isEqualTo(ptOnCurve))
           {
                      result = true;
                      return es;
           }
 
           // check its planar
           AcGePlane plane;
           AcDb::Planarity planarity;
           if((es = pCurve->getPlane(plane, planarity)) != Acad::eOk)
           {
                      return es;
           }
 
           if(planarity != AcDb::kPlanar)
           {
                      return Acad::eInvalidInput;
           }
 
           // make the test ray from the plane
           double epsilon = 2e-6; // ( trust me on this )
 
           AcGePoint3dArray IntersectionPoints;
           AcGeVector3d normal = plane.normal();
           AcGeVector3d testVector = normal.perpVector();
 
           AcDbRay ray;
           ray.setBasePoint(testPt);
 
           int nGlancingHits=0, numberOfInters=0;
           bool bRetryWithOtherRayDirection;
 
           do
           {
                      IntersectionPoints.removeAll();
                      bRetryWithOtherRayDirection = false;
                      ray.setUnitDir(testVector);
 
                      // fire the ray at the curve
                      if((es = pCurve->intersectWith(&ray, AcDb::kOnBothOperands, IntersectionPoints)) != Acad::eOk)
                                  return es;
 
                      numberOfInters = IntersectionPoints.length();
 
                      nGlancingHits = 0;
 
                      for(int i=0; i < numberOfInters; ++i)
                      {
                                // get the first point, and get its parameter
                                AcGePoint3d hitPt = IntersectionPoints[i];
 
                                double hitParam;
 
                                  //Circumvents an issue with AcDbCurve::getParamAtPoint API
                                  if((es = pCurve->getParamAtPoint(hitPt, hitParam )) != Acad::eOk)
                                  {
                                             bRetryWithOtherRayDirection = true;
                                             testVector.rotateBy(5.0 * 3.141592653/180.0, normal);
                                             break;
                                  }
 
                                  double inParam = hitParam - epsilon;
                                  double outParam = hitParam + epsilon;
 
                                  double startParam, endParam;
 
                                  pCurve->getStartParam(startParam);
                                  pCurve->getEndParam(endParam);
 
                                  //Loop back inside the curve if param is falling outside of range
                                  if (inParam < startParam)
                                             inParam = endParam - epsilon + (startParam - inParam);
 
                                  if (outParam > endParam)
                                             outParam = startParam + epsilon + (endParam - outParam);
 
                                  IncidenceType inIncidence = CurveIncidence(pCurve, inParam, testVector, normal);
                                  IncidenceType outIncidence = CurveIncidence(pCurve, outParam, testVector, normal);
 
                                  if (inIncidence == kIncidenceToFront || outIncidence == kIncidenceToFront)
                                  {
                                             bRetryWithOtherRayDirection = true;
                                             testVector.rotateBy(5.0 * 3.141592653/180.0, normal);
                                             break;
                                  }
 
                                  if( (inIncidence == kIncidenceToRight && outIncidence == kIncidenceToLeft) ||
                                  (inIncidence == kIncidenceToLeft && outIncidence == kIncidenceToRight))
                                  {
                                             ++nGlancingHits;
                                  }
                      }
           }
           while (bRetryWithOtherRayDirection);
 
           result = (( numberOfInters + nGlancingHits) % 2 == 1);
 
           return es;
}
 


游客,如果您要查看本帖隐藏内容请回复



论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 2457个

财富等级: 金玉满堂

发表于 2017-8-18 17:37:33 | 显示全部楼层
学习!!!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

已领礼包: 2个

财富等级: 恭喜发财

发表于 2017-8-19 09:34:21 | 显示全部楼层
学习!!!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

已领礼包: 2963个

财富等级: 家财万贯

发表于 2017-8-29 14:22:54 | 显示全部楼层
学习,谢谢分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 112个

财富等级: 日进斗金

发表于 2017-10-12 19:42:44 | 显示全部楼层
谢谢楼主分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 488个

财富等级: 日进斗金

发表于 2017-10-21 15:46:18 | 显示全部楼层
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

已领礼包: 6个

财富等级: 恭喜发财

发表于 2017-11-6 16:51:00 | 显示全部楼层
学习,谢谢分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 7个

财富等级: 恭喜发财

发表于 2018-7-20 12:45:40 | 显示全部楼层
学习!!!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

发表于 2019-4-12 01:55:02 | 显示全部楼层
正在学习中,谢谢。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 2个

财富等级: 恭喜发财

发表于 2019-7-24 09:13:32 | 显示全部楼层
学习!!!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

已领礼包: 1个

财富等级: 恭喜发财

发表于 2019-9-4 11:19:06 来自手机 | 显示全部楼层
学习下,谢谢
来自: 微社区
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2019-10-10 16:01:22 | 显示全部楼层
学习学习
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

发表于 2020-1-23 21:37:11 | 显示全部楼层

学习,谢谢分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2020-5-10 20:18:44 | 显示全部楼层
谢谢老大分享!学习学习
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 10个

财富等级: 恭喜发财

发表于 2020-9-23 00:20:32 | 显示全部楼层
thanks for code
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-10-23 11:34 , Processed in 0.382788 second(s), 56 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表