12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text.RegularExpressions;
- using Autodesk.Revit.DB;
- using SAGA.DotNetUtils;
- using SAGA.DotNetUtils.Extend;
- using SAGA.DotNetUtils.Geometry;
- using SAGA.RevitUtils.Infrastructure;
- using SAGA.RevitUtils.Utils;
- using Point = System.Windows.Point;
- namespace SAGA.RevitUtils.Extends
- {
- public static class UvExtend
- {
- public static UV MiddlePoint(this UV first, UV second)
- {
- double u = (first.U + second.U)/2;
- double v = (first.V + second.V)/2;
- UV midPoint = new UV(u, v);
- return midPoint;
- }
- }
- public static class XyzExtend
- {
- /// <summary>
- /// 获取两点距离信息
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="p2"></param>
- /// <returns></returns>
- public static PointDistanceInfo DistanceInfoTo(this XYZ p1, XYZ p2)
- {
- return new PointDistanceInfo(p1, p2);
- }
- /// <summary>
- /// 判断多点是否在同一直线上,另外判断点是否在线段上
- /// </summary>
- /// <param name="p1">所要判断点</param>
- /// <param name="p2">另外一点或线起点</param>
- /// <param name="p3">另外一点或线段终点</param>
- /// <param name="flag">false:判断是否在同一直线 true:判断是否在线段上</param>
- /// <returns></returns>
- /// 增加可选参数flag用于判断当前点是否在两点所组成的线段上
- public static bool IsInLine(this XYZ p1, XYZ p2, XYZ p3, bool flag = false)
- {
- PointDistanceInfo distance1 = p1.DistanceInfoTo(p2);
- PointDistanceInfo distance2 = p2.DistanceInfoTo(p3);
- PointDistanceInfo distance3 = p3.DistanceInfoTo(p1);
- PointDistanceInfo max = PointDistanceInfo.Max(new PointDistanceInfo[] {distance1, distance2, distance3});
- Line lineMaxLength =max.P1.NewLine( max.P2);
- XYZ[] points = new XYZ[] {p1, p2, p3};
- foreach (XYZ p in points)
- {
- if (!lineMaxLength.IsOnCurve(p))
- {
- return false;
- }
- }
- if (flag == true) //判断p1是否在线段p2,p3上
- {
- double length = distance1.Distance + distance3.Distance;
- if (length.IsEqual(distance2.Distance)) //若点在线段上,则点到两端点的距离之和为线段长度
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- return true;
- }
- /// <summary>
- /// 判断多点是否在同一直线
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="points"></param>
- /// <returns></returns>
- public static bool IsInLine(this XYZ pt, XYZ[] points)
- {
- if (points == null || points.Length < 2)
- {
- throw new ArgumentException("points");
- }
- List<XYZ> listPs = new List<XYZ>();
- listPs.Add(pt);
- listPs.AddRange(points);
- for (int i = 0; i < listPs.Count; i++)
- {
- int intMaxIndex = i + 2;
- if (intMaxIndex < listPs.Count)
- {
- XYZ p1 = listPs[i];
- XYZ p2 = listPs[i + 1];
- XYZ p3 = listPs[i + 2];
- if (!p1.IsInLine(p2, p3))
- {
- return false;
- }
- }
- }
- return true;
- }
- /// <summary>
- /// 将点移到指定点
- /// </summary>
- /// <param name="point"></param>
- /// <param name="origin"></param>
- /// <returns></returns>
- public static XYZ ConvertToPoint(this XYZ point, XYZ origin)
- {
- Transform tf = new Transform(Transform.Identity);
- {
- tf.BasisX = XYZ.BasisX;
- tf.BasisY = XYZ.BasisY;
- tf.BasisZ = XYZ.BasisZ;
- tf.Origin = origin;
- }
- return tf.OfPoint(point);
- }
- /// <summary>
- /// 将水平面三维坐标转换为二维坐标求叉积判断旋转关系
- /// 两个点若是水平面的点可以直接使用,若是不是水平面需要进行坐标转换
- /// 大于0:顺时针 等于0:共线
- /// </summary>
- /// <param name="left"></param>
- /// <param name="right"></param>
- /// <returns></returns>
- public static double VectorProduct(this XYZ left, XYZ right)
- {
- UV uv1 = new UV(left.X, left.Y);
- UV uv2 = new UV(right.X, right.Y);
- return uv1.CrossProduct(uv2);
- }
- /// <summary>
- /// 判断多点是否在同一直线上
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="points"></param>
- /// <returns></returns>
- public static bool IsOnLine(this XYZ pt, XYZ[] points)
- {
- return pt.IsInLine(points);
- }
- /// <summary>
- /// 判断点在线上
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="curve"></param>
- /// <returns></returns>
- public static bool IsOnCurve(this XYZ pt, Curve curve)
- {
- if (curve is Line)
- {
- Line line = curve as Line;
- return pt.IsOnLine(line);
- }
- if (curve is Arc)
- {
- Arc arc = curve as Arc;
- return pt.IsInArc(arc);
- }
- return false;
- }
- /// <summary>
- /// 点在线段上
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="line"></param>
- /// <returns></returns>
- public static bool IsOnLine(this XYZ pt, Line line)
- {
- return line.IsOnCurve(pt);
- }
- /// <summary>
- /// 判断点是否在弧上
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="arc"></param>
- /// <returns></returns>
- public static bool IsInArc(this XYZ pt, Curve arc)
- {
- return arc.IsOnCurve(pt);
- }
- /// <summary>
- /// 判断曲线是否存在于一个曲线集合里
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="listPoints"></param>
- /// <returns></returns>
- public static bool ExsitsInlist(this XYZ pt, IList<XYZ> listPoints, double tolerance = 0)
- {
- if (listPoints == null || listPoints.Count <= 0)
- {
- return false;
- }
- return listPoints.Contains(pt, new XyzEqualComparer(tolerance));
- }
- /// <summary>
- /// 转UV
- /// </summary>
- /// <param name="pt"></param>
- /// <returns></returns>
- public static UV ToUv(this XYZ pt)
- {
- return new UV(pt.X, pt.Y);
- }
- /// <summary>
- /// 转2DPoint
- /// </summary>
- /// <param name="pt"></param>
- /// <returns></returns>
- public static XYZ To2DPoint(this XYZ pt)
- {
- return pt.To2DPoint(XyzOptions.Z);
- }
- public static Point ToW2DPoint(this XYZ pt)
- {
- if (pt == null) return default(Point);
- return new Point(pt.X,pt.Y);
- }
- public static Geometry2D.PointD ToPointD(this XYZ pt)
- {
- return new Geometry2D.PointD(pt.X, pt.Y);
- }
- /// <summary>
- /// 转2DPoint
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="optionWhereToZero"></param>
- /// <returns></returns>
- public static XYZ To2DPoint(this XYZ pt, XyzOptions optionWhereToZero)
- {
- switch (optionWhereToZero)
- {
- case XyzOptions.X:
- return new XYZ(0, pt.Y, pt.Z);
- case XyzOptions.Y:
- return new XYZ(pt.X, 0, pt.Z);
- case XyzOptions.Z:
- default:
- return new XYZ(pt.X, pt.Y, 0);
- }
- }
- /// <summary>
- /// 比较某一值
- /// </summary>
- /// <param name="pt1"></param>
- /// <param name="pt2"></param>
- /// <param name="whereToCompare"></param>
- /// <returns></returns>
- public static int CompareTo(this XYZ pt1, XYZ pt2, XyzOptions whereToCompare)
- {
- double a = 0, b = 0;
- switch (whereToCompare)
- {
- case XyzOptions.X:
- a = pt1.X;
- b = pt2.X;
- break;
- case XyzOptions.Y:
- a = pt1.Y;
- b = pt2.Y;
- break;
- case XyzOptions.Z:
- a = pt1.Z;
- b = pt2.Z;
- break;
- }
- if (a == b)
- {
- return 0;
- }
- return (a > b) ? 1 : -1;
- }
- /// <summary>
- /// 比较
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <param name="optionHowCompare"></param>
- /// <returns></returns>
- public static int CompareTo(this XYZ first, XYZ second, DirectionEnum optionHowCompare, bool ignoreZ = false)
- {
- if (!first.Z.IsEqual(second.Z, 0.0) && !ignoreZ)
- {
- if (first.Z <= second.Z)
- {
- return -1;
- }
- return 1;
- }
- switch (optionHowCompare)
- {
- case DirectionEnum.LeftRight:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.LeftRightBottomTop:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- case DirectionEnum.LeftRightTopBottom:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.RightLeft:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- case DirectionEnum.RightLeftBottomTop:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return 1;
- }
- return -1;
- }
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- case DirectionEnum.RightLeftTopBottom:
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return 1;
- }
- return -1;
- }
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.BottomTop:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y <= second.Y)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.BottomTopLeftRight:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return 1;
- }
- return -1;
- }
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.BottomTopRightLeft:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return 1;
- }
- return -1;
- }
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- case DirectionEnum.TopBottom:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y <= second.Y)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- case DirectionEnum.TopBottomLeftRight:
- case DirectionEnum.LeftTopRightBottom:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return -1;
- }
- return 1;
- }
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- return 0;
- case DirectionEnum.TopBottomRightLeft:
- if (!first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.Y >= second.Y)
- {
- return -1;
- }
- return 1;
- }
- if (!first.X.IsEqual(second.X, 0.0))
- {
- if (first.X <= second.X)
- {
- return 1;
- }
- return -1;
- }
- return 0;
- }
- if (first.Y.IsEqual(second.Y, 0.0))
- {
- if (first.X.IsEqual(second.X, 0.0))
- {
- return 0;
- }
- if (optionHowCompare == DirectionEnum.LeftBottomRightTop)
- {
- if (first.X <= second.X)
- {
- return -1;
- }
- return 1;
- }
- if (first.X >= second.X)
- {
- return -1;
- }
- return 1;
- }
- if (first.Y <= second.Y)
- {
- return -1;
- }
- return 1;
- }
- /// <summary>
- /// 获取相对X轴倾斜角度,忽略Z轴,如果取圆上的点,则应该把圆上的点作为,起点 startPoint, 而圆心作为终点 endPoint
- /// </summary>
- /// <param name="endPt"></param>
- /// <param name="centerPt"></param>
- /// <returns></returns>
- public static double GetSlopeAngle(this XYZ endPt, XYZ centerPt)
- {
- XYZ vec = endPt.Subtract(centerPt);
- return (vec.QuadrantAngle().ToAngle() + 360)%360;
- }
- /// <summary>
- /// 获取相对X轴倾斜弧度
- /// </summary>
- /// <param name="endPt"></param>
- /// <param name="centerPt"></param>
- /// <returns></returns>
- public static double GetSlopeRadian(this XYZ endPt, XYZ centerPt)
- {
- XYZ vec = endPt.Subtract(centerPt);
- return vec.QuadrantAngle();
- }
- /// <summary>
- /// 矢量的象限角0到2Pi
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="xAxis"></param>
- /// <returns></returns>
- public static double QuadrantAngle(this XYZ vec, XYZ xAxis = null)
- {
- if (xAxis == null)
- {
- xAxis = XYZ.BasisX;
- }
- double dRtn = xAxis.AngleOnPlaneTo(vec, XYZ.BasisZ);
- if (dRtn.IsEqual(2*Math.PI))
- {
- dRtn = 0;
- }
- return dRtn;
- }
-
- /// <summary>
- /// 两个平面向量的夹角(锐角)
- /// </summary>
- /// <param name="vec1"></param>
- /// <param name="vec2"></param>
- /// <returns></returns>
- public static double GetAngle(this XYZ vec1, XYZ vec2)
- {
- double dRtn;
- if (vec1.IsSameDirection(vec2) || vec1.IsOppositeDirection(vec2))
- dRtn = 0;
- else
- //主要区别在这里,因为Z轴的方向不同
- dRtn = vec1.AngleOnPlaneTo(vec2, (vec1.CrossProduct(vec2)).Normalize());
- if (dRtn.IsEqual(2*Math.PI))
- {
- dRtn = 0;
- }
- return dRtn;
- }
- /// <summary>
- /// 两个平面向量的夹角,逆时针角
- /// </summary>
- /// <param name="vec1"></param>
- /// <param name="vec2"></param>
- /// <returns></returns>
- public static double GetAngle2(this XYZ vec1, XYZ vec2)
- {
- double dRtn = vec1.AngleOnPlaneTo(vec2, XYZ.BasisZ);
- if (dRtn.IsEqual(2*Math.PI))
- {
- dRtn = 0;
- }
- return dRtn;
- }
-
- /// <summary>
- /// 圆弧凸度
- /// </summary>
- /// <param name="ptC">圆心</param>
- /// <param name="ptS">起点</param>
- /// <param name="ptE">终点</param>
- /// <returns></returns>
- public static double GetArcBulge(this XYZ ptC, XYZ ptS, XYZ ptE)
- {
- if (ptE.IsEqual(ptS))
- return 0;
- XYZ vec1 = ptS - ptC;
- XYZ vec2 = ptE - ptC;
- double angle = vec1.AngleOnPlaneTo(vec2, XYZ.BasisZ);
- if (angle.IsLess(-Math.PI))
- angle += Math.PI*2;
- else if (angle.IsThan(Math.PI))
- angle -= Math.PI*2;
- return Math.Tan(angle/4);
- }
- /// <summary>
- /// 修改x值
- /// </summary>
- /// <param name="p1"></param>
- /// <returns></returns>
- public static XYZ NewX(this XYZ p1)
- {
- return p1.NewX(null);
- }
- /// <summary>
- /// 修改x值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="x"></param>
- /// <returns></returns>
- public static XYZ NewX(this XYZ p1, double? x)
- {
- double xValue = x.HasValue ? x.Value : 0;
- double y = p1.Y;
- double z = p1.Z;
- XYZ result = new XYZ(xValue, y, z);
- return result;
- }
- /// <summary>
- /// 增加x值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="x"></param>
- /// <returns></returns>
- public static XYZ AddX(this XYZ p1, double? x)
- {
- double xValue = x.HasValue ? x.Value : 0;
- double y = p1.Y;
- double z = p1.Z;
- XYZ result = new XYZ(p1.X + xValue, y, z);
- return result;
- }
- /// <summary>
- /// 修改y值
- /// </summary>
- /// <param name="p1"></param>
- /// <returns></returns>
- public static XYZ NewY(this XYZ p1)
- {
- return p1.NewY(null);
- }
- /// <summary>
- /// 修改y值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static XYZ NewY(this XYZ p1, double? y)
- {
- double x = p1.X;
- double yValue = y.HasValue ? y.Value : 0;
- double z = p1.Z;
- XYZ result = new XYZ(x, yValue, z);
- return result;
- }
- /// <summary>
- /// 增加y值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static XYZ AddY(this XYZ p1, double? y)
- {
- double x = p1.X;
- double yValue = y.HasValue ? y.Value : 0;
- double z = p1.Z;
- XYZ result = new XYZ(x, p1.Y + yValue, z);
- return result;
- }
- /// <summary>
- /// 修改z值
- /// </summary>
- /// <param name="p1"></param>
- /// <returns></returns>
- public static XYZ NewZ(this XYZ p1)
- {
- return p1.NewZ(null);
- }
- /// <summary>
- /// 修改z值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="z"></param>
- /// <returns></returns>
- public static XYZ NewZ(this XYZ p1, double? z)
- {
- double x = p1.X;
- double y = p1.Y;
- double zValue = z.HasValue ? z.Value : 0;
- XYZ result = new XYZ(x, y, zValue);
- return result;
- }
- /// <summary>
- /// 增加z值
- /// </summary>
- /// <param name="p1"></param>
- /// <param name="z"></param>
- /// <returns></returns>
- public static XYZ AddZ(this XYZ p1, double? z)
- {
- double x = p1.X;
- double y = p1.Y;
- double zValue = z.HasValue ? z.Value : 0;
- XYZ result = new XYZ(x, y, p1.Z + zValue);
- return result;
- }
- /// <summary>
- /// 创建线
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <returns></returns>
- public static Line NewLine(this XYZ first, XYZ second)
- {
- return Line.CreateBound(first, second);
- }
- /// <summary>
- /// 两个坐标是否相等(包含Z坐标)
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <param name="tolerance"></param>
- /// <returns></returns>
- public static bool IsEqual(this XYZ first, XYZ second, double tolerance = 0)
- {
- return (first.X.IsEqual(second.X, tolerance)
- && first.Y.IsEqual(second.Y, tolerance)
- && first.Z.IsEqual(second.Z, tolerance));
- }
- /// <summary>
- /// 两个坐标是否相等(不包含Z坐标)
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <param name="tolerance">误差范围</param>ls 2015-01-04添加
- /// <returns></returns>
- public static bool IsEqual2(this XYZ first, XYZ second, double tolerance = 0)
- {
- return first.NewZ().IsEqual(second.NewZ(), tolerance);
- }
- /// <summary>
- /// 相等处理
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <param name="whereNotEqual"></param>
- /// <param name="tolerance"></param>
- /// <returns></returns>
- public static bool IsEqual(this XYZ first, XYZ second, XyzOptions whereNotEqual, double tolerance = 0)
- {
- switch (whereNotEqual)
- {
- case XyzOptions.X:
- return (first.Y.IsEqual(second.Y, tolerance)
- && first.Z.IsEqual(second.Z, tolerance));
- case XyzOptions.Y:
- return (first.X.IsEqual(second.X, tolerance)
- && first.Z.IsEqual(second.Z, tolerance));
- case XyzOptions.Z:
- default:
- return (first.X.IsEqual(second.X, tolerance)
- && first.Y.IsEqual(second.Y, tolerance));
- }
- }
- /// <summary>
- /// 转API
- /// </summary>
- /// <param name="xyz"></param>
- /// <returns></returns>
- public static XYZ ConvertToApi(this XYZ xyz)
- {
- double x = xyz.X.ToApi();
- double y = xyz.Y.ToApi();
- double z = xyz.Z.ToApi();
- return new XYZ(x, y, z);
- }
- /// <summary>
- /// 转项目单位
- /// </summary>
- /// <param name="xyz"></param>
- /// <returns></returns>
- public static XYZ ConvertFromApi(this XYZ xyz)
- {
- double x = xyz.X.FromApi();
- double y = xyz.Y.FromApi();
- double z = xyz.Z.FromApi();
- return new XYZ(x, y, z);
- }
- public static XYZ FromApi(this XYZ xyz,DisplayUnitType unitType=DisplayUnitType.DUT_MILLIMETERS)
- {
- double x = xyz.X.FromApi(unitType);
- double y = xyz.Y.FromApi(unitType);
- double z = xyz.Z.FromApi(unitType);
- return new XYZ(x, y, z);
- }
- /// <summary>
- /// 取整
- /// </summary>
- /// <param name="xyz"></param>
- /// <returns></returns>
- public static XYZ Round(this XYZ xyz, int digits = 0)
- {
- return new XYZ(xyz.X.Round(digits), xyz.Y.Round(digits), xyz.Z.Round(digits));
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="xyz"></param>
- /// <param name="format"></param>
- /// <returns></returns>
- public static string ToString(this XYZ xyz, string format)
- {
- if (format == null || format.Length <= 0)
- {
- format = "{0},{1},{2}";
- }
- return string.Format(format, xyz.X, xyz.Y, xyz.Z);
- }
- /// <summary>
- /// 转换为字符串
- /// </summary>
- /// <param name="xyz"></param>
- /// <returns></returns>
- public static string ToString2(this XYZ xyz)
- {
- string format = "[{0},{1},{2}]";
- return xyz.ToString(format);
- }
- /// <summary>
- /// 转换为二维坐标字符串
- /// </summary>
- /// <param name="xyz"></param>
- /// <returns></returns>
- public static string ToString2D(this XYZ xyz)
- {
- string format = "[{0}, {1}]";
- return string.Format(format, Math.Round(xyz.X, 2), Math.Round(xyz.Y, 2));
- }
- /// <summary>
- /// Transform old coordinate system in the new coordinate system
- /// </summary>
- /// <param name="pt">the XYZ which need to be transformed</param>
- /// <param name="transform">the value of the coordinate system to be transformed</param>
- /// <returns>the new XYZ which has been transformed</returns>
- public static XYZ TransformPoint(this XYZ pt, Transform transform)
- {
- //get the coordinate value in X, Y, Z axis
- double x = pt.X;
- double y = pt.Y;
- double z = pt.Z;
- //transform basis of the old coordinate system in the new coordinate system
- XYZ b0 = transform.get_Basis(0);
- XYZ b1 = transform.get_Basis(1);
- XYZ b2 = transform.get_Basis(2);
- XYZ origin = transform.Origin;
- //transform the origin of the old coordinate system in the new coordinate system
- double xTemp = x*b0.X + y*b1.X + z*b2.X + origin.X;
- double yTemp = x*b0.Y + y*b1.Y + z*b2.Y + origin.Y;
- double zTemp = x*b0.Z + y*b1.Z + z*b2.Z + origin.Z;
- return new XYZ(xTemp, yTemp, zTemp);
- }
- /// <summary>
- /// Move a pt a give offset along a given direction
- /// </summary>
- /// <param name="pt">the pt need to move</param>
- /// <param name="direction">the direction the pt move to</param>
- /// <param name="offset">indicate how long to move</param>
- /// <returns>the moved pt</returns>
- public static XYZ OffsetPoint(this XYZ pt, XYZ direction, double offset)
- {
- XYZ directUnit = direction.Normalize();
- XYZ offsetVect = directUnit.Multiply(offset);
- return pt.Add(offsetVect);
- }
- /// <summary>
- /// 两点间的中点
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <returns></returns>
- public static XYZ MiddlePoint(this XYZ first, XYZ second)
- {
- double x = (first.X + second.X)/2;
- double y = (first.Y + second.Y)/2;
- double z = (first.Z + second.Z)/2;
- XYZ midPoint = new XYZ(x, y, z);
- return midPoint;
- }
- /// <summary>
- /// 两点距离(参考z轴)
- /// </summary>
- /// <param name="first">the first pt</param>
- /// <param name="second">the first pt</param>
- /// <returns>the distance of two points</returns>
- public static double FindDistance(this XYZ first, XYZ second)
- {
- return first.DistanceTo(second);
- }
- /// <summary>
- /// 两点距离(忽略z轴)
- /// </summary>
- /// <param name="first">the first pt</param>
- /// <param name="second">the first pt</param>
- /// <returns>the distance of two points</returns>
- public static double FindDistance2(this XYZ first, XYZ second)
- {
- return first.NewZ().FindDistance(second.NewZ());
- }
- /// <summary>
- /// Find the direction vector from first pt to second pt
- /// </summary>
- /// <param name="first">the first pt</param>
- /// <param name="second">the second pt</param>
- /// <returns>the direction vector</returns>
- public static XYZ FindDirection(this XYZ first, XYZ second)
- {
- return second.Subtract(first).Normalize();
- }
- /// <summary>
- /// 点在圆内
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="curveList"></param>
- /// <returns></returns>
- public static bool PointInCircle(this XYZ pt, List<Curve> curveList)
- {
- if (curveList.Count != 2)
- {
- return false;
- }
- Arc arc1 = curveList[0].GetArc();
- Arc arc2 = curveList[1].GetArc();
- if ((arc1 == null) || (arc2 == null))
- {
- return false;
- }
- CurveLoop loop = CurveLoop.Create(curveList);
- if (loop.IsOpen())
- {
- return false;
- }
- XYZ ptCenter = arc1.StartPoint().MiddlePoint(arc1.EndPoint());
- double dR = arc1.StartPoint().FindDistance2(arc1.EndPoint())/2;
- if (pt.FindDistance2(ptCenter).IsLess(dR))
- {
- return true;
- }
- return false;
- }
- /// <summary>
- /// 判断点是否在多边形内
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="curveList">组成多边形的线</param>
- /// <returns></returns>
- /// 原理:根据点水平向左做射线,若与多边形单边交点为奇数则此点在内部,反之在外部
- public static bool PointInPoly(this XYZ pt, List<Curve> curveList)
- {
- Line line = Line.CreateUnbound(pt, new XYZ(-1, 0, 0)); //水平向左射线
- int i = 0;
- List<double> dList = new List<double>();
- curveList.ForEach(delegate(Curve p)
- {
- dList.Add(p.StartPoint().Y);
- dList.Add(p.EndPoint().Y);
- });
- foreach (Curve curve in curveList)
- {
- if (curve.StartPoint().Y.IsEqual(curve.EndPoint().Y)) continue;
- if (curve.IsIntersection(line))
- {
- XYZ xyz = curve.GetIntersections(line)[0];
- if (xyz.X > pt.X) continue;
- double minY = Math.Min(curve.StartPoint().Y, curve.EndPoint().Y);
- double maxY = Math.Max(curve.StartPoint().Y, curve.EndPoint().Y);
- //如果交点为最高点或最低点,则点肯定不在多边形内
- if (xyz.Y.IsEqual(dList.Max()) || xyz.Y.IsEqual(dList.Min())) continue;
- //判断是交点为线段端点,只取纵坐标最大的那个
- if (xyz.Y != minY)
- {
- i++;
- }
- }
- }
- if (i%2 == 0) return false;
- return true;
- }
- /// <summary>
- /// 判断点是否在多边形中
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="listProfile"></param>
- /// <returns></returns>
- public static bool PointInPolygon2(this XYZ pt, IList<Curve> listProfile)
- {
- try
- {
- List<XYZ> listPt = new List<XYZ>();
- foreach (Curve curve in listProfile)
- {
- XYZ ptS = curve.StartPoint();
- XYZ ptE = curve.EndPoint();
- if (!ptS.ExsitsInlist(listPt))
- {
- listPt.Add(ptS);
- }
- if (!ptE.ExsitsInlist(listPt))
- {
- listPt.Add(ptE);
- }
- }
- double anglesum = 0;
- int n = listPt.Count;
- for (int i = 0; i < n; i++)
- {
- XYZ pt1 = listPt[i];
- XYZ pt2 = listPt[(i + 1)%n];
- XYZ v1 = pt1 - pt;
- XYZ v2 = pt2 - pt;
- double len1 = v1.GetLength();
- double len2 = v2.GetLength();
- if ((len1*len2).IsEqual(0))
- {
- return true;
- }
- else
- {
- double cosa = v1.DotProduct(v2)/(len1*len2);
- anglesum += Math.Acos(cosa);
- }
- }
- return anglesum.IsEqual(2*Math.PI);
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 点按照Z轴旋转
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="angle">弧度(逆时针为正角)</param>
- /// <param name="origin"></param>
- /// <returns></returns>
- public static XYZ PointRotate(this XYZ pt, double angle, XYZ origin)
- {
- XYZ vec = new XYZ(pt.X - origin.X, pt.Y - origin.Y, pt.Z - origin.Z);
- vec = vec.VectorRotate(angle, origin);
- return origin + vec;
- }
- /// <summary>
- /// 向量以Z轴为参照轴绕原点旋转
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="angle"></param>
- /// <returns></returns>
- public static XYZ VectorRotate(this XYZ vec, double angle)
- {
- return vec.VectorRotate(angle, XYZ.Zero);
- }
- /// <summary>
- /// 向量(点)绕任意轴旋转
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="axis">参照轴</param>
- /// <param name="angle"></param>
- /// <returns></returns>
- public static XYZ VectorRotate(this XYZ vec, XYZ axis, double angle)
- {
- return vec.VectorRotate(XYZ.Zero, axis, angle);
- }
- /// <summary>
- /// 向量绕Z轴旋转
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="angle">弧度</param>
- /// <param name="origin">参照点</param>
- /// <returns></returns>
- public static XYZ VectorRotate(this XYZ vec, double angle, XYZ origin)
- {
- return vec.VectorRotate(origin, XYZ.BasisZ, angle);
- }
- /// <summary>
- /// 向量绕任意轴旋转
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="origin">旋转所绕点</param>
- /// <param name="axis">旋转所绕的轴</param>
- /// <param name="angle">旋转角度</param>
- /// <returns></returns>
- public static XYZ VectorRotate(this XYZ vec, XYZ origin, XYZ axis, double angle)
- {
- Transform transform = Transform.CreateRotationAtPoint(axis,angle,origin);
- return transform.OfVector(vec);
- }
- /// <summary>
- /// 向量反向
- /// </summary>
- /// <param name="vec"></param>
- /// <returns></returns>
- [Obsolete("方法已过时,请使用API中方法XYZ.Negate()")] //ls 2015-08-15
- public static XYZ Revert(this XYZ vec)
- {
- return -vec;
- }
- /// <summary>
- /// 两向量垂直
- /// </summary>
- /// <param name="vec1"></param>
- /// <param name="vec2"></param>
- /// <returns></returns>
- public static bool IsVertical(this XYZ vec1, XYZ vec2, double tolerance = 0.0)
- {
- return vec1.DotProduct(vec2).IsEqual(0.0, tolerance);
- }
- /// <summary>
- /// 两向量平行
- /// </summary>
- /// <param name="vec1"></param>
- /// <param name="vec2"></param>
- /// <returns></returns>
- public static bool IsParallel(this XYZ vec1, XYZ vec2, double tolerance = 0)
- {
- return vec1.Normalize().IsEqual(vec2.Normalize(), tolerance)
- || vec1.Normalize().IsEqual(vec2.Normalize().Negate(), tolerance);
- }
- /// <summary>
- /// 向量方向相同
- /// </summary>
- /// <param name="firstVec"></param>
- /// <param name="secondVec"></param>
- /// <returns></returns>
- public static bool IsSameDirection(this XYZ firstVec, XYZ secondVec)
- {
- //a.b = |a|*|b|*cos<a,b>
- // get the unit vector for two vectors
- XYZ first = firstVec.Normalize();
- XYZ second = secondVec.Normalize();
- // if the dot product of two unit vectors is equal to 1, return true
- #region ls 2015-03-14注释
- double dot = first.DotProduct(second);
- return (dot.IsEqual(1, 0.001));
- #endregion
- //return firstVec.IsEqual(secondVec);
- }
- /// <summary>
- /// 向量方向相反
- /// </summary>
- /// <param name="firstVec"></param>
- /// <param name="secondVec"></param>
- /// <returns></returns>
- public static bool IsOppositeDirection(this XYZ firstVec, XYZ secondVec)
- {
- //a.b = |a|*|b|*cos<a,b>
- // get the unit vector for two vectors
- XYZ first = firstVec.Normalize();
- XYZ second = secondVec.Normalize();
- // if the dot product of two unit vectors is equal to -1, return true
- double dot = first.DotProduct(second);
- return (dot.IsEqual(-1));
- }
- /// <summary>
- /// 比较
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <param name="curve"></param>
- /// <param name="blnStart">从起点开始</param>
- /// <returns></returns>
- //public static int CompareTo(this XYZ first, XYZ second, Curve curve, bool blnStart)
- //{
- // if (!blnStart)
- // {
- // curve = curve.Reverse();
- // }
-
- // if (curve.IsLine())
- // {
- // Line line = curve.GetLine();
- // double xDist = line.StartPoint().FindDistance2(first);
- // double yDist = line.StartPoint().FindDistance2(second);
- // if (xDist.IsEqual(yDist))
- // {
- // return 0;
- // }
- // else
- // {
- // return xDist > yDist ? 1 : -1;
- // }
- // }
- // if (curve.IsLine())
- // {
- // Line line = curve.GetLine();
- // double xDist = line.StartPoint().FindDistance2(first);
- // double yDist = line.StartPoint().FindDistance2(second);
- // if (xDist.IsEqual(yDist))
- // {
- // return 0;
- // }
- // else
- // {
- // return xDist > yDist ? 1 : -1;
- // }
- // }
- // return 0;
- //}
- public static int CompareTo(this XYZ first, XYZ second, Curve curve, bool blnStart)
- {
- if (!blnStart)
- {
- curve = curve.Reverse();
- }
- if (curve.IsArc())
- {
- Arc arc = curve.GetArc();
- double startAngle = arc.GetStartAngle(first);
- double num2 = arc.GetStartAngle(second);
- if (startAngle.IsEqual(num2, 0.0))
- {
- return 0;
- }
- if (startAngle <= num2)
- {
- return -1;
- }
- return 1;
- }
- if (!curve.IsLine())
- {
- return 0;
- }
- Line line = curve.GetLine();
- double num3 = line.StartPoint().FindDistance2(first);
- double num4 = line.StartPoint().FindDistance2(second);
- if (num3.IsEqual(num4, 0.0))
- {
- return 0;
- }
- if (num3 <= num4)
- {
- return -1;
- }
- return 1;
- }
- /// <summary>
- /// 向量过一点的直线
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="pt"></param>
- /// <param name="d"></param>
- /// <param name="blnMid"></param>
- /// <returns></returns>
- public static Line VectorToLine(this XYZ vec, XYZ pt, double d, bool blnMid = false)
- {
- if (blnMid)
- {
- return Line.CreateBound(pt - vec*d, pt + vec*d);
- }
- else
- {
- return Line.CreateBound(pt, pt + vec*d);
- }
- }
- /// <summary>
- /// 向量过一点的射线
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="pt"></param>
- /// <returns></returns>
- public static Line VectorToLine(this XYZ vec, XYZ pt)
- {
- return Line.CreateUnbound(pt, vec);
- }
- /// <summary>
- /// 创建直线
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="vec"></param>
- /// <param name="d"></param>
- /// <param name="blnMid"></param>
- /// <returns></returns>
- public static Line PointToLine(this XYZ pt, XYZ vec, double d, bool blnMid = false)
- {
- return vec.VectorToLine(pt, d, blnMid);
- }
- /// <summary>
- /// 创建射线
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="vec"></param>
- /// <returns></returns>
- public static Line PointToLine(this XYZ pt, XYZ vec)
- {
- return vec.VectorToLine(pt);
- }
- /// <summary>
- /// 参照十字线
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="dLen"></param>
- /// <returns></returns>
- public static List<DetailCurve> GetCorssLine(this XYZ pt, double dLen = 0)
- {
- ExternalDataWrapper wrapper = ExternalDataWrapper.Current;
- XYZ basisX = wrapper.ActiveView.RightDirection;
- XYZ basisY = wrapper.ActiveView.UpDirection;
- XYZ basisZ = wrapper.ActiveView.ViewDirection;
- List<DetailCurve> listCurCross = new List<DetailCurve>();
- if (dLen == 0)
- dLen = 100000d.ToApi();
- Line line = basisX.VectorToLine(pt, dLen, true);
- DetailCurve detailLine = wrapper.Doc.Create.NewDetailCurve(wrapper.ActiveView, line);
- detailLine.SetLineStyle(SysLineStyles.LinesHiddenLines);
- listCurCross.Add(detailLine);
- line = basisY.VectorToLine(pt, dLen, true);
- detailLine = wrapper.Doc.Create.NewDetailCurve(wrapper.ActiveView, line);
- detailLine.SetLineStyle(SysLineStyles.LinesHiddenLines);
- listCurCross.Add(detailLine);
- wrapper.Doc.Regenerate();
- return listCurCross;
- }
- /// <summary>
- /// 项目中用到的迹线
- /// </summary>
- /// <param name="first"></param>
- /// <param name="second"></param>
- /// <returns></returns>
- public static List<DetailCurve> NewTraceLine(this XYZ first, XYZ second)
- {
- List<DetailCurve> listCurCross = new List<DetailCurve>();
- ExternalDataWrapper wrapper = ExternalDataWrapper.Current;
- Line line = Line.CreateBound(first, second);
- DetailCurve detailLine = wrapper.Doc.Create.NewDetailCurve(wrapper.ActiveView, line);
- detailLine.SetLineStyle(SysLineStyles.LinesHiddenLines);
- listCurCross.Add(detailLine);
- wrapper.Doc.Regenerate();
- return listCurCross;
- }
- /// <summary>
- /// 根据两顶点获取矩形 wzc
- /// </summary>
- /// <param name="maxb">最大坐标顶点</param>
- /// <param name="minb">最小坐标顶点</param>
- /// <returns></returns>
- public static List<Line> GetRectange(this XYZ maxb, XYZ minb)
- {
- Line l1 = Line.CreateBound(maxb.NewX(minb.X), maxb); //上
- Line l2 = Line.CreateBound(maxb, maxb.NewY(minb.Y)); //右
- Line l3 = Line.CreateBound(maxb.NewY(minb.Y), minb.NewZ(maxb.Z)); //下
- Line l4 = Line.CreateBound(minb.NewZ(maxb.Z), maxb.NewX(minb.X)); //左
- List<Line> lines = new List<Line>();
- lines.Add(l1);
- lines.Add(l2);
- lines.Add(l3);
- lines.Add(l4);
- return lines;
- }
- /// <summary>
- /// 是否为曲线的端点
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="curve"></param>
- /// <param name="tolerance"></param>
- /// <returns></returns>
- public static bool IsEndPoint(this XYZ pt, Curve curve, double tolerance = 0)
- {
- return pt.IsEqual(curve.StartPoint(), tolerance) || pt.IsEqual(curve.EndPoint(), tolerance);
- }
- /// <summary>
- /// 按逆时针排序点集(未考虑Z方向)
- /// </summary>
- /// <param name="ptList"></param>
- public static void SortAnticlockwise(this List<XYZ> ptList)
- {
- XYZ center = new XYZ();
- double x = 0, y = 0, z = 0;
- for (int i = 0; i < ptList.Count; i++)
- {
- x += ptList[i].X;
- y += ptList[i].Y;
- z += ptList[i].Z;
- }
- double mx = x / ptList.Count;
- double my = y / ptList.Count;
- double mz = z / ptList.Count;
- center = new XYZ(mx, my, mz);
- for (int i = 0; i < ptList.Count - 1; i++)
- {
- for (int j = 0; j < ptList.Count - i - 1; j++)
- {
- if (PointCmp(ptList[j], ptList[j + 1], center))
- {
- XYZ tmp = ptList[j];
- ptList[j] = ptList[j + 1];
- ptList[j + 1] = tmp;
- }
- }
- }
- }
- /// <summary>
- /// 若a大于点b,即点a在b顺时针方向 ,返回true,否则false
- /// 为SortAnticlockwise方法调用
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- /// <param name="center"></param>
- /// <returns></returns>
- private static bool PointCmp(XYZ a, XYZ b, XYZ center)
- {
- if (a.X >= 0 && b.X < 0)
- return true;
- if (a.X == 0 && b.X == 0)
- return a.Y > b.Y;
- //向量OA和OB的叉积
- double det = ((a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y));
- if (det < 0)
- return true;
- if (det > 0)
- return false;
- //向量OA和向量OB共线,以距离判断大小
- double d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y);
- double d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y);
- return d1 > d2;
- }
- /// <summary>
- /// 矢量的象限角0到2Pi
- /// </summary>
- /// <param name="vec"></param>
- /// <param name="xAxis"></param>
- /// <param name="normal"></param>
- /// <returns></returns>
- public static double QuadrantAngle(this XYZ vec, XYZ xAxis, XYZ normal)
- {
- double num = xAxis.AngleOnPlaneTo(vec, normal);
- if (num.IsEqual(6.2831853071795862, 0.0))
- {
- num = 0.0;
- }
- return num;
- }
- /// <summary>
- /// 点是否在线上
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="line"></param>
- /// <param name="tolerance"></param>
- /// <returns></returns>
- public static bool IsInLine(this XYZ pt, Line line, double tolerance = 0.0)
- {
- return line.IsContain(pt, tolerance);
- }
- /// <summary>
- /// 判断点是否在多边形内
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="listProfile"></param>
- /// <returns></returns>
- public static bool PointInPolygon(this XYZ pt, IList<Curve> listProfile)
- {
- var flag = true;
- //if (!pt.PointInPoly1(listProfile))
- //{
- // flag = pt.PointInPoly2(listProfile.ToList<Curve>());
- //}
- //点在边框上,也要判定为在多边形内部
- flag = pt.PointInPolygonByRay(listProfile.OfType<Line>().ToList())>=0;
- return flag;
- }
- /// <summary>
- /// 判断点是否在多边形中 ljy
- /// 此方法李林提供,好象也不准确与PointInPoly2一起使用
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="listProfile"></param>
- /// <returns></returns>
- private static bool PointInPoly1(this XYZ pt, IList<Curve> listProfile)
- {
- try
- {
- List<XYZ> listPoints = new List<XYZ>();
- foreach (Curve curve in listProfile)
- {
- XYZ xyz = curve.StartPoint();
- XYZ xyz2 = curve.EndPoint();
- if (!xyz.ExsitsInlist(listPoints, 0.0))
- {
- listPoints.Add(xyz);
- }
- if (!xyz2.ExsitsInlist(listPoints, 0.0))
- {
- listPoints.Add(xyz2);
- }
- }
- double num = 0.0;
- int count = listPoints.Count;
- for (int i = 0; i < count; i++)
- {
- XYZ xyz3 = listPoints[i];
- XYZ xyz4 = listPoints[(i + 1) % count];
- XYZ xyz5 = xyz3 - pt;
- XYZ source = xyz4 - pt;
- double length = xyz5.GetLength();
- double num5 = source.GetLength();
- if ((length * num5).IsEqual(0.0, 0.0))
- {
- return true;
- }
- double d = xyz5.DotProduct(source) / (length * num5);
- num += Math.Acos(d);
- }
- return num.IsEqual(6.2831853071795862, 0.0);
- }
- catch
- {
- return false;
- }
- }
- /// <summary>
- /// 判断点是否在多边形内(水平射线法)
- /// 此方法网上提供,好象也不准确与PointInPoly1一起使用
- /// </summary>
- /// <param name="pt"></param>
- /// <param name="curveList"></param>
- /// <returns></returns>
- public static bool PointInPoly2(this XYZ pt, List<Curve> curveList)
- {
- Line line = Line.CreateUnbound(pt, new XYZ(-1.0, 0.0, 0.0));
- int num = 0;
- List<double> dList = new List<double>();
- curveList.ForEach(delegate (Curve p) {
- dList.Add(p.StartPoint().Y);
- dList.Add(p.EndPoint().Y);
- });
- foreach (Curve curve in curveList)
- {
- if (!curve.StartPoint().Y.IsEqual(curve.EndPoint().Y, 0.0) && curve.IsIntersection(line, 0.0))
- {
- XYZ xyz = curve.GetIntersections(line, 0.0)[0];
- if (xyz.X <= pt.X)
- {
- double num2 = Math.Min(curve.StartPoint().Y, curve.EndPoint().Y);
- Math.Max(curve.StartPoint().Y, curve.EndPoint().Y);
- if ((!xyz.Y.IsEqual(((IEnumerable<double>)dList).Max(), 0.0) && !xyz.Y.IsEqual(((IEnumerable<double>)dList).Min(), 0.0)) && (xyz.Y != num2))
- {
- num++;
- }
- }
- }
- }
- if ((num % 2) == 0)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 通过射线法判断点是否在封闭区域内
- /// </summary>
- /// <param name="inputPoint"></param>
- /// <param name="lines"></param>
- /// <returns>
- /// 如果点在多边形内: 返回1
- /// 如果点在多边形边上: 返回0
- /// 如果点在多边形外: 返回-1
- /// </returns>
- public static int PointInPolygonByRay(this XYZ inputPoint, List<Line> lines)
- {
- #region 描述
- /*
- * 判断点是否在直线所围成的区域内;
- * 结果三种,-1,在外侧;0,在边上,1,在多边形内
- * 判断焦点奇偶
- * 如果交点是线段的端点,则记录这个点的信息,同一个交点算一次焦点。
- * 如果线段恰巧和射线共线,如果点在射线中,则记录一个点。否则该记录几个点,就记录几个点;
- * 这个不考虑阿拉伯数字⑧字形这种种,轮廓线有非端点相交情况,这种情况需要记录焦点的具体值
- */
- #endregion
- //以给定点,向x正方向做射线
- //线段端点在射线上的集合
- //List<XYZ> points = new List<XYZ>();
- List<PointGroup> groups = new List<PointGroup>();
- //默认是偶数
- bool isEven = true;
- double baseX = inputPoint.X;
- double baseY = inputPoint.Y;
- foreach (var line in lines)
- {
- var start = line.StartPoint();
- var end = line.EndPoint();
- if (start.IsEqual(inputPoint) || end.IsEqual(inputPoint))
- {
- return 0;
- }
- //判断给定线的端点是否在射线两侧,利用水平线的性质
- if ((start.Y.IsLessEq(baseY) && baseY.IsLessEq(end.Y)) || (end.Y.IsLessEq(baseY) && baseY.IsLessEq(start.Y)))
- {
- double minX = Math.Min(start.X, end.X);
- double maxX = Math.Min(start.X, end.X);
- if (start.Y.IsEqual(end.Y))
- {
- #region 与给定射线共线处理
- //给定线段与射线平行
- if (minX.IsLessEq(baseX) && baseX.IsLessEq(maxX))
- {
- return 0;
- }
- else if (baseX.IsLess(minX))
- {
- PointGroup.AddGroup(groups, new PointGroup() { start, end });
- }
- #endregion
- }
- else if (baseX.IsLessEq(maxX))
- {
- //当给定线,小于等于线最大坐标时,才有可能相交
- /*
- * p1(x1,x2) vecter(xv,yv)
- * x1+xv*c=x
- * y1+yv*c=y
- * 求出c,带入公式1
- */
- double c = (baseY - start.Y) / (end.Y - start.Y);
- double useX = start.X + c * (end.X - start.X);
- if (useX.IsEqual(baseX))
- {
- //给定点,在线上
- return 0;
- }
- if (baseX.IsLessEq(useX))
- {
- //这种情况下肯定相交
- var intersectionPoint = new XYZ(useX, baseY,0);
- if (start.IsEqual(intersectionPoint))
- {
- PointGroup.AddGroup(groups, new PointGroup() { start });
- }
- else if (end.IsEqual(intersectionPoint))
- {
- PointGroup.AddGroup(groups, new PointGroup() { end });
- }
- else
- {
- isEven = !isEven;
- }
- }
- }
- }
- }
- //整理通过的端点
- if (groups.Any())
- {
- foreach (var group in groups)
- {
- var usePoint = group.FirstOrDefault();
- var refLines = lines.Where(l => LineUtil.GetPosition(l, usePoint) != -1).ToList();
- if (refLines.Count < 2)
- {
- continue;
- }
- List<double> results = new List<double>();
- foreach (Line line in refLines)
- {
- List<Line> useLines = new List<Line>(lines);
- useLines.Remove(line);
- var extendPoint = LineUtil.GetFirstPoint(useLines, usePoint, p => !p.Y.IsEqual(usePoint.Y));
- results.Add(extendPoint.Y);
- }
- if (results[0].IsLess(baseY) == results[1].IsThan(baseY))
- {
- if (!results[0].IsEqual(baseY) && !results[1].IsEqual(baseY))
- {
- isEven = !isEven;
- }
- }
- }
- }
- return isEven ? -1 : 1;
- }
- /// <summary>
- /// 通过射线法判断点是否在封闭区域内
- /// </summary>
- /// <param name="inputPoint"></param>
- /// <param name="points"></param>
- /// <returns>
- /// 如果点在多边形内: 返回1
- /// 如果点在多边形边上: 返回0
- /// 如果点在多边形外: 返回-1
- /// </returns>
- public static int PointInPolygonByRay(this XYZ inputPoint, List<XYZ> points)
- {
- #region 老方法
- //List<Line> lines = new List<Line>();
- //for (int i = 0; i < points.Count; i++)
- //{
- // var start = points[i];
- // var end = points[(i + 1) % points.Count];
- // lines.Add(Line.CreateBound(start, end));
- //}
- //return PointInPolygonByRay(inputPoint, lines);
- #endregion
- bool isEven = true;
- double baseX = inputPoint.X;
- double baseY = inputPoint.Y;
- var total = points.Count;
- for (int i = 0; i < total; i++)
- {
- var endIndex = (i + 1) % total;
- var start = points[i];
- var end = points[endIndex];
- if (start.IsEqual2(inputPoint) || end.IsEqual2(inputPoint))
- {
- return 0;
- }
- bool isEndIntersection = false;//判断交点是否是end
- //判断给定线的端点是否在射线两侧,利用水平线的性质
- if ((start.Y.IsLessEq(baseY) && baseY.IsLessEq(end.Y)) || (end.Y.IsLessEq(baseY) && baseY.IsLessEq(start.Y)))
- {
- double minX = Math.Min(start.X, end.X);
- double maxX = Math.Min(start.X, end.X);
- if (start.Y.IsEqual(end.Y))
- {
- #region 与给定射线共线处理
- //给定线段与射线平行
- if (minX.IsLessEq(baseX) && baseX.IsLessEq(maxX))
- {
- return 0;
- }
- else if (baseX.IsLess(minX))
- {
- isEndIntersection = true;
- }
- #endregion
- }
- else if (baseX.IsLessEq(maxX))
- {
- double c = (baseY - start.Y) / (end.Y - start.Y);
- double useX = start.X + c * (end.X - start.X);
- if (useX.IsEqual(baseX))
- {
- //给定点,在线上
- return 0;
- }
- if (baseX.IsLessEq(useX))
- {
- //这种情况下肯定相交
- var intersectionPoint = new XYZ(useX, baseY,0);
- if (end.IsEqual2(intersectionPoint))
- {
- //开始点不处理
- isEndIntersection = true;
- }
- else if (start.IsEqual2(intersectionPoint))
- {
- isEndIntersection = false;
- }
- else
- {
- isEven = !isEven;
- }
- }
- }
- if (isEndIntersection)
- {
- var end2 = points[(endIndex + 1) % total];
- if (!baseY.IsEqual(end2.Y))
- {
- var point = points.GetFirstElement(endIndex, p => !p.Y.IsEqual(baseY), false);
- if (end2.Y.IsLess(baseY) == point.Y.IsThan(baseY))
- {
- //排除同时相等的情况
- if (!end2.Y.IsEqual(baseY) && !point.Y.IsEqual(baseY))
- {
- isEven = !isEven;
- }
- }
- }
- }
- }
- }
- return isEven ? -1 : 1;
- }
- }
- }
|