1

次のSVGファイルを見てください。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10,10 10,390 390,390 10,10" style="fill:rgb(140,90,90)" />
<polygon points="10,10 390,390 390,10 10,10" style="fill:rgb(90,140,90)" />
</svg>

これを試してみると、2つの三角形には薄い灰色の領域があり、それらを分離しています。何百もの小さな三角形があるので、これらを取り除きたいと思います。そうすると、三角形で覆われているはずの領域に、分離線がグリッドとして表示されます。MathematicaのSVGエクスポートにはまさにこの問題があることに気づきました。

同じ色と幅1のストロークで輪郭を塗りつぶそうとしましたが、三角形が塗りつぶされてしまいました。したがって、外観は三角形が描かれる順序によって異なります。

この問題に対するクリーンな解決策または少なくとも改善点はありますか?

4

3 に答える 3

1

表示されるのは、ベクターグラフィックをビットマップデバイスにマッピングした結果のようです。それを補うために、1単位未満の量で関係する三角形の1つをわずかに摂動させます。

例(コードは以下を参照):紫色のポリゴンをx軸に沿って0.2単位シフトして変換します。

結果の品質は、明らかな要因は別として、ズーム率に依存することに注意してください。与えられた例では、クロム25で> = 150%のズームレベルで分離線が消えるのを見ることができます。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10.2,10   10.2,390 390.2,390 10.2,10" style="fill:rgb(140,90,90)" />
<polygon points="  10,10    390,390   390,10    10,10" style="fill:rgb(90,140,90)" />
</svg>

もう1つのオプションは、三角形の一部を五角形に変更することです。これは、三角形間の分離線をカバーする隣接する台形領域(以下のコードを参照)で、67%を超えるズーム率で機能します。三角形と平面内でのそれらの方向(1つの直角、直交格子上の辺など)に制約はありますか?

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10,10  10,390  390,390 390,389.6 10.4,10 10,10" style="fill:rgb(140,90,90)" />
<polygon points="10,10      390,390 390,10  10,10"               style="fill:rgb(90,140,90)" />
</svg>
于 2013-03-26T08:50:38.850 に答える
1

これは使用されたラスタライズ戦略の結果であり、簡単な修正はありません。

1つの修正は、三角形をストロークすることですが、非常に細いストロークで行います。たとえば、ストロークが0.2pxの場合は次のようになります。

デモ: http: //jsfiddle.net/Qw2HL/

または、グラフィックを2倍にして、実際のコンテンツの下にストロークバージョンをレンダリングすることもできます。

デモ: http: //jsfiddle.net/Qw2HL/1/

<g id="underlay">
  <polygon class="t1" points="10,10 10,390 390,390 10,10" />
  <polygon class="t2" points="10,10 390,390 390,10 10,10" />
</g><g id="content">
  <polygon class="t1" points="10,10 10,390 390,390 10,10" />
  <polygon class="t2" points="10,10 390,390 390,10 10,10" />
</g>
.t1 { fill:rgb(140,90,90); stroke:rgb(140,90,90) }
.t2 { fill:rgb(90,140,90); stroke:rgb(90,140,90) }
#underlay polygon { stroke-width:1px }
#content  polygon { stroke:none      }

(これは、利用可能なWebブラウザーなどのユーザーエージェントで実行している場合は、JSを介して自動的に実行できます。)


このデモは、問題を非常に明確に示しています。

問題: http: //jsfiddle.net/tbCxT/

<svg xmlns="http://www.w3.org/2000/svg">
  <g id="aligned">
    <polygon class="a" points="10,10 10,100 100,100, 100,10" />
    <polygon class="b" points="100,10 100,100 200,100, 200,10" />
  </g>
  <g id="shifted" transform="translate(0.5,110)">
    <polygon class="a" points="10,10 10,100 100,100, 100,10" />
    <polygon class="b" points="100,10 100,100 200,100, 200,10" />
  </g>
</svg>

ここでは、2つの垂直エッジが正確に重なり合っています。最初のケースでは、それらはピクセルグリッド上に正確に配置されます。左の形状は左のすべてのピクセルを正確に塗りつぶし、右の形状は右のすべてのピクセルを正確に塗りつぶし、どちらもギャップを越えて塗りつぶしません。

ただし、2番目のケースでは、両方の形状がピクセル境界の間にあります。形状がこれらのピクセルと50%重なっているため、この場合、アンチエイリアシングにより、正確に50%の不透明度で重なっているピクセルを塗りつぶす必要があることがわかります。したがって、左側の形状はこの共有列のピクセルを50%不透明で塗りつぶし、右側の形状は共有列をさらに50%不透明なピクセルで塗りつぶします。

残念ながら、不透明度は加算ではなく乗算によって構築されます。rgba(0,0,0,0.5)のオーバートップのピクセルは、ではなく、をrgba(0,0,0,0.5)生成rgba(0,0,0,0.75)rgba(0,0,0,1)ます。

これが問題の核心であり、SVGに固有のものではありません。たとえば、次を参照してください。

無限精度のベクター画像を有限ピクセルグリッドにサンプリングすると、情報が失われます。あなたはそれを回避するためにハックする必要があります。

于 2013-03-26T13:51:30.117 に答える
1

エッジを共有するポリゴン間のスペースについても同じ問題がありました。これは、さまざまな不透明度を持つ1つのエッジを共有する2つの三角形です。

http://jsfiddle.net/YfH9N/embedded/result/

...ポリゴンの不透明度が高いほど、スペースが見やすくなります。他の回答で示唆されているように、ストロークのアウトラインをポリゴンに追加すると役立ちますが、ストロークの正しい幅はポリゴンの不透明度によって異なります。

一定の1pxのストローク幅を使用する:

http://jsfiddle.net/LKQHf/embedded/result/

ストローク幅の使用=polygon_alpha^ 6:

http://jsfiddle.net/ekwk3/2/embedded/result/

...このPerlスクリプトを使用して経験的にのみストローク幅の式を見つけたので、自分で試すことができます。

#!/usr/bin/perl

print "<?xml version=\"1.0\" standalone=\"no\"?>
<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">
<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1100\" height=\"100\">
";

for (my $alpha = 0; $alpha<=1; $alpha+=0.025) {
    my $alpha_str = sprintf("%.3f", $alpha);
    my $alpha_stroke = 1;#$alpha ** 6;
    my $alpha_stroke_str = sprintf("%.3f", $alpha_stroke);
    my $stroke_width = $alpha ** 6;
    my $stroke_width_str = sprintf("%.3fpx", $stroke_width);

    print "
    <g transform=\"translate(".($alpha*1000).",0)\">    
        <polygon points=\"20,10 25,49 6,40\" style=\"fill:rgb(255,100,0);fill-opacity:$alpha_str;stroke:rgb(255,100,0);stroke-width:$stroke_width_str;stroke-opacity:$alpha_stroke_str\" />
        <polygon points=\"20,10 25,49 40,4\" style=\"fill:rgb(255,100,0);fill-opacity:$alpha_str;stroke:rgb(255,100,0);stroke-width:$stroke_width_str;stroke-opacity:$alpha_stroke_str\" />
    </g>\n";
}

print "</svg>";
于 2014-06-17T13:09:05.780 に答える