Path Markup – 楕円弧の描画について


こんにちは、Platform SDK (Windows SDK) サポートチームです。

 WPF は、「Loose XAML」と呼ばれるコンパイル不要なマークアップを読み込み、Internet Explorer 内に描画する機能を持っています。

今回は、Loose XAML で非常に大きな楕円弧を書いた場合、始点と終点が正しい位置に描画されない事象が見られることをご紹介します。

 例えば、次のようなコードを記述し、拡張子 .xaml で保存します。

これにより、Loose XAML ファイルが作成されます。

このファイルを Internet Explorer 11 で表示した場合、WPF のレンダリングエンジンによって、図 1のような楕円弧が描かれます。

 

 

<?xml version=”1.0″ encoding=”utf-8″?>

  <Canvas  Background=”#ffffff” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>

    <Canvas.RenderTransform>

       <TransformGroup>

            <TranslateTransform X=”-26000″ Y=”-3000″ />

        </TransformGroup>

     </Canvas.RenderTransform>

 
   <Path Stroke=”#ff0000″>

      <Path.Data>

          <PathGeometry Figures=”M 26557.35,3320.226 A 1703595,1703595,0,1,0,26569.29,3290.773″/>

     </Path.Data>

    </Path>

 </Canvas>

 

上記は PathGeometry 要素により、Figures 属性中の M で指定した絶対座標 26557.35,3320.226 から、A の第六引数、第七引数で指定した、絶対座標 26569.29,3290.773 に向けて楕円弧を描く、というものです。

その際、楕円弧の径として、A の第一引数、第二引数が x 半径と y 半径として使用されますが、上記では両方とも 1703595 であり、真円による円弧が描かれています。

A の第三引数では楕円の回転角を設定しており、ここでは、0 度を指定しています。

第四引数では円弧の角度が 180 度を超えるか ( 1を指定)、超えないか ( 0 に指定) を設定しますが、ここでは、1 を指定することで大きな円弧を描いています。

また、第五引数では 0 または1 を指定することで、始点と終点に対してどちら側に楕円の中心が存在するかを指定できます。

 

ここで上記の A の第四引数を0 に変更して Internet Explorer で表示した場合、図 2 のような楕円弧が描かれます。

 

 

<?xml version=”1.0″ encoding=”utf-8″?>

  <Canvas  Background=”#ffffff” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>

    <Canvas.RenderTransform>

     <TransformGroup>

       <TranslateTransform X=”-26000″ Y=”-3000″ />

     </TransformGroup>

    </Canvas.RenderTransform>

  

  <Path Stroke=”#ff0000″>

     <Path.Data>

        <PathGeometry Figures=”M 26557.35,3320.226 A 1703595,1703595,0,0,0,26569.29,3290.773″/>

     </Path.Data>

   </Path>

 </Canvas>

 

0を指定したことにより内側に向かって小さい楕円弧を描画していますが、始点と終点が大きくずれてしまっているのがわかります。

実際ここで同じ始点と終点により、以下のように楕円弧ではなく線分を描いた場合が図3 ですが、これと比較するとよりはっきりします。

<?xml version=”1.0″ encoding=”utf-8″?>

  <Canvas  Background=”#ffffff” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>

 
   <Canvas.RenderTransform>

       <TransformGroup>

          <TranslateTransform X=”-26000″ Y=”-3000″ />

       </TransformGroup>

   </Canvas.RenderTransform>

   <Path Stroke=”#ff0000″>

     <Path.Data>

        <PathGeometry Figures=”M 26557.35,3320.226 L 26569.29,3290.773“/> 

     </Path.Data>

   </Path>

 </Canvas>

 

この動作は、WPF のレンダリングエンジンが内部で使用している DirectX (Direct3D9) の影響を受けています。

Direct3D9 は、単精度 (10進数における有効桁数ほぼ 7 桁) により計算が行われているため、楕円弧などの複雑な計算を行う場合には、予期しない結果になる可能性があります。

今回のように限りなく直線に近い円弧を描画する際に問題が発生する場合は、上記 図3のように線分で置き換えてしまうことが最も簡単な回避方法となります。