马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
[C#] 纯文本查看 复制代码 enum IncidenceType
{
kIncidenceToLeft = 0,
kIncidenceToRight,
kIncidenceToFront,
kIncidenceUnknown
};
IncidenceType CurveIncidence(Curve curve, double param, Vector3d dir, Vector3d normal)
{
Vector3d deriv1 = curve.GetFirstDerivative(param);
if(deriv1.IsParallelTo(dir))
{
// need second degree analysis
Vector3d deriv2 = curve.GetSecondDerivative(param);
if( deriv2.IsZeroLength() || deriv2.IsParallelTo(dir))
{
return IncidenceType.kIncidenceToFront;
}
else
{
if(deriv2.CrossProduct(dir).DotProduct(normal) < 0)
{
return IncidenceType.kIncidenceToRight;
}
else
{
return IncidenceType.kIncidenceToLeft;
}
}
}
if(deriv1.CrossProduct(dir).DotProduct(normal) < 0)
{
return IncidenceType.kIncidenceToLeft;
}
else
{
return IncidenceType.kIncidenceToRight;
}
}
bool IsInsideCurve(Curve curve, Point3d testPt)
{
if(!curve.Closed)
{
// cannot be inside
return false;
}
Point3d ptOnCurve = curve.GetClosestPointTo(testPt, false);
if( testPt == ptOnCurve)
{
return true;
}
if(!curve.IsPlanar)
{
return false;
}
// check its planar
Plane plane = curve.GetPlane();
// make the test ray from the plane
double epsilon = 2e-6; // ( trust me on this )
Point3dCollection IntersectionPoints = new Point3dCollection();
Vector3d normal = plane.Normal;
Vector3d testVector = normal.GetPerpendicularVector();
using (Ray ray = new Ray())
{
ray.BasePoint = testPt;
int nGlancingHits = 0, numberOfInters = 0;
bool bRetryWithOtherRayDirection;
do
{
bRetryWithOtherRayDirection = false;
IntersectionPoints.Clear();
ray.UnitDir = testVector;
// fire the ray at the curve
curve.IntersectWith(ray,
Intersect.OnBothOperands,
IntersectionPoints,
IntPtr.Zero,
IntPtr.Zero);
numberOfInters = IntersectionPoints.Count;
if (numberOfInters == 0)
{
return false;
}
nGlancingHits = 0;
for (int i = 0; i < IntersectionPoints.Count; ++i)
{
double hitParam;
try
{
//This try/catch block circumvents an issue with GetParameterAtPoint API
hitParam = curve.GetParameterAtPoint(IntersectionPoints[i]);
}
catch
{
bRetryWithOtherRayDirection = true;
testVector = testVector.RotateBy(5.0 * Math.PI / 180.0, normal);
break;
}
double inParam = hitParam - epsilon;
double outParam = hitParam + epsilon;
//Loop back inside the curve if param is falling outside of range
if (inParam < curve.StartParam)
inParam = curve.EndParam - epsilon + (curve.StartParam - inParam);
if (outParam > curve.EndParam)
outParam = curve.StartParam + epsilon + (curve.EndParam - outParam);
IncidenceType inIncidence = CurveIncidence(curve, inParam, testVector, normal);
IncidenceType outIncidence = CurveIncidence(curve, outParam, testVector, normal);
if (inIncidence == IncidenceType.kIncidenceToFront || outIncidence == IncidenceType.kIncidenceToFront)
{
bRetryWithOtherRayDirection = true;
testVector = testVector.RotateBy(5.0 * Math.PI / 180.0, normal);
break;
}
if ((inIncidence == IncidenceType.kIncidenceToRight && outIncidence == IncidenceType.kIncidenceToLeft) ||
(inIncidence == IncidenceType.kIncidenceToLeft && outIncidence == IncidenceType.kIncidenceToRight))
{
nGlancingHits++;
}
}
}
while (bRetryWithOtherRayDirection);
return ((numberOfInters + nGlancingHits) % 2 == 1);
}
}
[C#] 纯文本查看 复制代码
[CommandMethod("TestIsInsideCurve")]
public void TestIsInsideCurve()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityOptions peo = new PromptEntityOptions("\nSelect a Curve: ");
peo.SetRejectMessage("\nInvalid selection...");
peo.AddAllowedClass(typeof(Curve), false);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
PromptPointResult ppr = ed.GetPoint("\nPick a point");
if (ppr.Status != PromptStatus.OK)
return;
using (Transaction Tx = db.TransactionManager.StartTransaction())
{
Curve curve = Tx.GetObject(per.ObjectId, OpenMode.ForRead) as Curve;
bool res = IsInsideCurve(curve, ppr.Value);
ed.WriteMessage("\nInside: " + res.ToString());
}
}
|