標籤:sub log 換算 add 座標 mode tar dynamic 可行性
許久沒寫部落格了,最近在研究WPF下氣泡的畫法,研發過程還是比較艱辛的(主要是複習了高中的數學知識,MMP全忘光了),這篇部落客要是提供一個思路給大家參考,如果有大神還有更好的解決方案可以不吝您的言論盡情留言。拿個這個類型的功能項目,首先分析可以假設氣泡是由:橢圓/矩形/圓(橢圓的特例)和三角形組成,OK首先分步驟介紹研發步驟:
第一:首先我的所有的圖形都是基於矩陣畫出來的,座標軸起點是(0,0),假設一個拖拉點DynamicPoint (x,y),和一個固定點FixedPoint (m,n);由兩點即可確定一個矩形大小,從裡面畫出內接圖形和一個三角形;
1、建立矩形 var TriagleRect = new Rect(FixedPoint, DynamicPoint);
2、假設矩形之記憶體在一個等比例大小的圓,而圓是由圓心和半徑組成的直線所划過的弧確定的,半徑R,圓心CenterXY (p,q);相當於已知
3、可以移動的點P設為:CurrentFixedPoint(s,t); 這個點是由滑鼠捕獲的相當於已知;
4、由動點CurrentFixedPoint(s,t)向圓 M(圓心為CenterXY (p,q),半徑R)作兩條圓的切線,求出兩切點F1(f1x,f1y)、F2(f2x,f2y)座標值?
如(做的圖比較難看,做輔助之用)
到這邊肯定很多人覺得很熟悉,沒錯這是高中的數學題,這邊在研究的過程中研究了兩種解決方案,下面簡單的介紹下:
方案1:
,由圓心點C向兩切點做垂直線,然後根據三角函數做輔助線PQ,QC得出斜邊PC長,由圖中可以知道
double Sine = R / AB; //求出正弦值
∠F1PC= Math.Round((Math.Asin(Sine) / Math.PI) * 180, 2);//把正弦值換算成角度
利用向量和向量模進行計算二元一次方程可以得出F1,F2座標.
方程1:PF1向量=PC向量+CF1向量 ,這裡可以得出一個關於F1的二元一次方程;
方程2:PF1向量的模=(PC平方+CF1平方)開根號,這裡可以得出一個關於F1的二元二次方程;
由這兩個方程式可以解出F1的座標值,同理也可以得出F2的座標值;
方案2:
也是,方案1是稍微複雜了一點,比較不利於軟體當中的應用,這邊著重介紹第二種算出切點的可行性方案;
double MB = Math.Sqrt(Math.Pow(PC, 2) - Math.Pow(R, 2));//MB為切線的長度
double Sine = R / AB; //求出正弦值
∠F1PC= Math.Round((Math.Asin(Sine) / Math.PI) * 180, 2);//把正弦值換算成角度
接下來跟方案1不同的地方是:我要讓圓心點按照角度∠F1PC進行順逆時針進行旋轉
1 //把移動點作為圓心按照角度SineAngle旋轉,有方向,順逆時針 2 Vector vector = Point.Subtract(CenterXY, CurrentFixedPoint); 3 Matrix matrix = new Matrix(); 4 matrix.RotateAt(SineAngle, CurrentFixedPoint.X, CurrentFixedPoint.Y); 5 //轉換成單位向量1 6 var v = matrix.Transform(vector); 7 v.Normalize(); 8 9 Matrix matrix2 = new Matrix();10 matrix2.ScaleAt(_vector, _vector, CurrentFixedPoint.X, CurrentFixedPoint.Y);11 var v2 = matrix2.Transform(v);12 return v2;
經過上面旋轉,然後縮放到單位1的向量假設為PF1‘ ,然後按比例放大到PF1的模長之後得出向量PF1,這樣就可以得出F1點座標,同理得出F2;具體轉換如下:
1 //根據獲得的向量值求出切點的座標值2 var tmpPoint = Point.Add(P, SecondPoint);3 var tmpPoint2 = Point.Add(P, ThirdPoint);
這樣就實現了移動動點P,F1,F2也會跟著角度進行即時變化,但是夾角不變,OK,現在動態兩個點都已經確認出來了,接下來就可以通過C#提供的方法進行連線,這樣就組成了一個三角形,這個三角形是由內圓心出發延伸至動點P的圖形。
1 //開始連線畫點2 PathFigure PointPathFigure = new PathFigure();3 PointPathFigure.StartPoint = CurrentFixedPoint;4 PointPathFigure.Segments.Add(new LineSegment(new Point(tmpPoint.X, tmpPoint.Y), true));5 PointPathFigure.Segments.Add(new LineSegment(new Point(tmpPoint2.X, tmpPoint2.Y), true));6 7 PathGeometry myPathGeometry = new PathGeometry();8 myPathGeometry.Figures.Add(PointPathFigure);
第二:兩個獨立圖形出來之後那就是組合圖形了,C#組合圖形提供了一個專門的方法:Geometry.Combine(Geometry geometry1, Geometry geometry2, GeometryCombineMode mode, Transform transform),不多說不懂得可以查閱資料; 備忘:ellipse 是第一個形狀,四個中心點分別位於矩陣的邊上;
1 //組合圖形2 var geometry = Geometry.Combine(myPathGeometry, ellipse, GeometryCombineMode.Union, null);3 4 this.DrawGeometry(streamGeometryContext, geometry);
如下:下面是任意移動動點P之後的效果。個人思路僅供參考。(這是原創文章,如有轉載,請備忘清楚)
C# WPF動點任意移動氣泡畫法(解決方案使用到數學勾股定理、正弦定理、向量知識)。