使用缠绕数指向多边形问题是:如何判断一个点是否在多边形内部?这个问题已经被问过和回答过很多次了。有多种方法可以确定一个点是否在多边形内。我了解了绕数算法,将另一个SO线程的可靠答案移植到C#中并围绕它编写了xUnit测试以确保我可以无情地重构。目标是得到一个答案,所有这些似乎都使用类似于您在数学公式中找到的过程编程方法和变量名,并将其重构为一组合理合理的OOP类和方法。因此,将这个问题具体改写为我将继续提供的答案:Howtodetermineifalocation/point(latitudeandlongitude)iswithinapolygoninOOPC#?我用作起点的答案是由ManuelCastro在以下SO线程GeoFencing-PointingIn/OutPolygons中提供的:poly.Add(newLatLong{Lat=poly[0].Lat,Lon=poly[0].Lon});LatLong[]v=poly.ToArray();intwn=0;//绕组数计数器//遍历多边形的所有边for(inti=0;ip.Lat)//向上交叉if(isLeft(v[i],v[i+1],p)>0)//P边的左边++wn;//有一个有效的向上相交}else{//开始y>Py(不需要测试)if(v[i+1].Lat我开始写一个实现,从xUnit测试上面的代码中表达的确切逻辑开始。以下有点矫枉过正,但我??更愿意进行更多测试以确保重构不会产生问题。在xUnit理论中使用内联数据非常容易,呃,为什么不呢。所有测试都是绿色的,然后我才能重构我心的内容:publicclassPolygonTests{publicclassGivenLine:PolygonTests{privatereadonlyPolygon_polygon=newPolygon(newList{newGeographicalPoint(1,1),newGeographicalPoint(10),1)});publicclassAndPointIsAnywhere:GivenLine{[Theory]??[InlineData(5,1)][InlineData(-1,-1)][InlineData(11,11)]publicvoidWhenAskingContainsLocation_ThenItShouldReturnFalse(双纬度,双经度){GeographicalPointpoint=new地理点(纬度,经度);boolactual=_polygon.Contains(point);实际.应该().BeFalse();}}}publicclassGivenTriangle:PolygonTests{privatereadonlyPolygon_polygon=newPolygon(newList{newGeographicalPoint(1,1),newGeographicalPoint(10,1),newGeographicalPoint(10,10)});publicclassAndPointWithinTriangle:GivenTriangle{privatereadonlyGeographicalPoint_point=newGeographicalPoint(6,4);[事实]publicvoidWhenAskingContainsLocation_ThenItShouldReturnTrue(){boolactual=_polygon.Contains(_point);实际.应该().BeTrue();}}publicclassAndPointOutsideOfTriangle:GivenTriangle{privatereadonlyGeographicalPoint_point=newGeographicalPoint(5,5.0001d);[事实]publicvoidWhenAskingContainsLocation_ThenItShouldReturnFalse(){boolactual=_polygon.Contains(_point);实际.应该().BeFalse();}}}publicclassGivenComplexPolygon:PolygonTests{privatereadonlyPolygon_polygon=newPolygon(newList{newGeographicalPoint(1,1),newGeographicalPoint(5,1),newGeographicalPoint(8,4),newGeographicalPoint(3,4)),新地理点(8,9),新地理点(1,9)});[理论][InlineData(5,0,false)][InlineData(5,0.999d,false)][InlineData(5,1,true)][InlineData(5,2,true)][InlineData(5,3),true)][InlineData(5,4,false)][InlineData(5,5,false)][InlineData(5,5.999d,false)][InlineData(5,6,true)][InlineData(5,5,7,真)][InlineData(5,8,真)][InlineData(5,9,false)][InlineData(5,10,false)][InlineData(0,5,false)][InlineData(0.999d,5,false)][InlineData(1,5,true)][InlineData(2,5,true)][InlineData(3,5,true)][InlineData(4.001d,5,false)]//[InlineData(5,5,false)]--复制[InlineData(6),5,false)][InlineData(7,5,false)][InlineData(8,5,false)][InlineData(9,5,false)][InlineData(10,5,false)]publicvoidWhenAskingContainsLocation_ThenItShouldReturnCorrectAnswer(双纬度,双经度,boolexpected){GeographicalPointpoint=newGeographicalPoint(latitude,longitude);boolactual=_polygon.Contains(point);actual.Should().Be(预期);}}}这允许我将原始代码重结构为以下内容:publicinterfaceIPolygon{boolContains(GeographicalPointlocation);}publicclassPolygon:IPolygon{privatereadonlyList_points;公共多边形(列表点){_points=points;}publicboolContains(GeographicalPointlocation){GeographicalPoint[]polygonPointsWithClosure=PolygonPointsWithClosure();int绕组数=0;对于(intpointIndex=0;pointIndex(_points){newGeographicalPoint(_points[0].Latitude,_points[0].Longitude)}.ToArray();}privatestaticintAscendingIntersection(GeographicalPointlocation,Edgeedge){if(!edge.AscendingRelativeTo(location)){return0;}if(!edge.LocationInRange(location,Orientation.Ascending)){return0;}returnWind(location,edge,Position.Left);}privatestaticintDescendingIntersection(GeographicalPointlocation,Edgeedge){if(edge.AscendingRelativeTo(location)){return0;}if(!edge.LocationInRange(location,Orientation.Descending)){返回0;}returnWind(location,edge,Position.Right);}privatestaticintWind(GeographicalPointlocation,Edgeedge,Positionposition){if(edge.RelativePositionOf(location)!=position){return0;}return1;}privateclassEdge{privatereadonlyGeographicalPoint_startPoint;privatereadonly地理点_endPo诠释;publicEdge(GeographicalPointstartPoint,GeographicalPointendPoint){_startPoint=startPoint;_endPoint=终点;}publicPositionRelativePositionOf(GeographicalPointlocation){doublepositionCalculation=(_endPoint.Longitude-_startPoint.Longitude)*(location.Latitude-_startPoint.Latitude)-(location.Longitude-_startPoint.Longitude)*(_endPoint.Latitude-_startPoint.Latitude);if(positionCalculation>0){returnPosition.Left;}if(positionCalculationlocation.Latitude;return_endPoint.Latitude当然,原始代码没有那么冗长,但是它:是过程性的;使用不透露意图的变量名;是可变的;圈复杂度为12。重构代码:通过测试;包含最少的元素(上面给出的1、2和3)并且:面向对象;除了保护子句外不使用;不可变;隐藏其私有数据;具有完整的测试覆盖率;只有一种方法,圈复杂度3,虽然大多数方法是1,但其中一些是2。现在,所有这些,我并不是说没有可能建议的额外重构,或者上述重构接近完美。但是,我认为在实现绕圈数时,这有助于查看算法以确定一个点是否在多边形中并实际理解该算法。我希望这能帮助像我这样在绕圈时遇到困难的人。干杯以上是C#学习教程:用缠绕数指向多边形共享的全部内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处:
