2010-04-07 24 views
2

交點鑑於像這樣的路徑之一:在Silverlight/WPF

<Path Stretch="Fill" Stroke="#FFD69436" Data="M 0,20 L 22.3,20 L 34,0 L 44.7,20 L 68,20 L 55.8,40 L 68,60 L 44.7,60 L 34,80 L 22.3,60 L 0,60 L 11.16,40 L 0,20 Z"> 
      <Path.Fill> 
       <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 
        <LinearGradientBrush.GradientStops> 
         <GradientStop Color="#FFFFFF" Offset="0" /> 
         <GradientStop Color="Orange" Offset="1" /> 
        </LinearGradientBrush.GradientStops> 
       </LinearGradientBrush> 
      </Path.Fill> 
     </Path> 

我怎樣才能像在這個數字在任何角度的邊緣點?比方說,我想要這個圖的邊緣和穿過這個圖的中心的線之間的交點,與OX斧頭成30度角?

謝謝。

回答

5

有很多不同的方法可以做到這一點,這取決於您需要的性能和準確性以及您願意編寫多少幾何代碼。

1.使用FillContains

的一種方法是構造連續線的幾何形狀和使用path.Data.FillContains(幾何形狀),以確定它們是否相交的附圖。沿着這些路線的東西:

Transform rotation = new RotateTransform { Angle = 30 }; 

double max = path.Width + path.Height; 
double current = 0; 
for(double delta = max/2; delta > 0.25; delta = delta/2) 
{ 
    var line = new LineGeometry(
        new Point(centerX + current, centerY), 
        new Point(centerX + max, centerY), 
        rotation); 
    if(path.Data.FillContains(line)) 
    current += delta; 
} 
var intersectPoint = rotation.Transform(new Point(current, 0)); 

2.使用GetFlattenedPathGeometry

另一種方法是使用GetFlattenedPathGeometry:

var flattened = path.Data.GetFlattenedPathGeometry(); 
var segment = pg.Figures[0].Segments[0] as PolyLineSegment; 
Point[] points = segment.Points; 
for(int i=0; i<points.Count-1; i++) 
{ 
    ... check for intersection with the line from points[i] to points[i+1] ... 
} 

這可能是更快,因爲幾何只處理一次,但需要你編寫自己的直線交點算法(這非常簡單)。

3.使用PathGeometry.CreateFromGeometry

所有的最有效的方式是把已知幾何轉換成的PathGeometry,然後通過在幾何圖和段手動迭代:

變種地理= PathGeometry.CreateFromGeometry(path.Data); 的foreach(在geo.Figures VAR圖) 的foreach(在figure.Segments VAR段) 如果(段是線段) ... 否則,如果(段ArcSegment) ... 否則,如果(段BezierSegment ) ... 否則,如果(段QuadraticBezierSegment) ... 否則,如果(段PolyLineSegment) ... 否則,如果(段PolyBezierSegment) ... 否則,如果(段PolyQuadraticBezierSegment) ...

這種方法需要相當多的幾何分析代碼,但速度非常快,因爲WPF不必構造扁平幾何體或重複交叉。當我需要我的代碼運行速度非常快時,這是我通常使用的技術。在GetWidenedPathGeometry

注意

一切到目前爲止,我說給你交叉口幾何路徑的數據和相貫線之間:它沒有考慮到線寬,端蓋等。要考慮這些因素,以及你將需要使用GetWidenedPathGeometry如下:

var widenedData = path.Data.GetWidenedPathGeometry(new Pen { ... }); 

在筆參數從path.Stroke,path.StrokeWidth設置等

這樣做了以後,用一個上述技術將「path.Data」替換爲「widenedData」。

+0

感謝...我會這樣。 – 2010-04-09 09:10:00

1

你們知道Silverlight 3中的相應功能嗎?我試圖爲WP7做這件事,它看起來像Paths.Data是一個普通的幾何對象,它不公開數字或你提到的方法。順便說

偉大的答案,這真的幫了我,我試圖從路徑得到點集合,這是它,它只是doesnn't工作,爲移動:)

+0

同樣,它並沒有幫助,因爲在WP7上這些方法不可用。我希望他們在那裏。 :( – Marc 2010-10-30 04:14:26

+0

但是,這個http://stringtopathgeometry.codeplex.com/和這可能有助於http://www.codeproject.com/KB/silverlight/PathAnimation.aspx – Marc 2010-10-30 04:24:24