2011-07-08 24 views

答えて

29

まず、raphaelなどの優れたグラフィックスライブラリを使用することをおすすめします。実際にjavascriptを使用して図面を実行するプロセスを簡略化します。

スムージングの非常に単純な方法は、すべてのlinetoコマンドを同等のcurvetoコマンドで変換し、各ラインセグメントの角度に基づいていくつかの制御点を計算することです。例えば、

<svg width="1000" height="1000" version="1.1" 
xmlns="http://www.w3.org/2000/svg"> 

<path d=" 
M250 150 
L150 350 
L350 350 
L250 150 
" /> 

</svg> 

は、これらの両方は正三角形次のステップでは、制御点の位置を計算することであろう

を描画する

<svg width="1000" height="1000" version="1.1" 
xmlns="http://www.w3.org/2000/svg"> 

<path d=" 
M250 150 
C250 150 150 350 150 350 
C150 350 350 350 350 350 
C350 350 250 150 250 150 
" /> 

</svg> 

となります。一般に、滑らかなコーナーの両側のコントロールポイントは、頂点を通過する仮想線に当たるようにします。正三角形の頂点の場合、これは水平線です。

<svg width="1000" height="1000" version="1.1" 
xmlns="http://www.w3.org/2000/svg"> 

<path d=" 
M250 150 
C230 150 140 333 150 350 
C160 367 340 367 350 350 
C360 333 270 150 250 150 
" /> 

</svg> 

トリッキーな部分は、コントロールポイントを計算しているが、それは、単純な三角の問題以下、はるかに変わる:いくつかの操作をした後、あなたはこのような何かを得ることができます。前述したように、ここでの目標は、コーナー頂点を2等分する線上に2つのコントロールポイントを配置することです。我々は2つの線分があると、例えば、:

A. (0,0) to (3,2) 
B. (0,0) to (1,-4) 

the absolute angle of A is arctan(2/3) = 33.69 deg 
the absolute angle of B is arctan(-4/1) = -75.96 deg 
the bisection angle of AB is (33.69 + -75.96)/2 = -21.135 
the tangent angle is AB is (-21.135 + 90) = 68.865 

接線角度を知ることを、我々は制御点位置を算出することができる

smoothness = radius = r 
tangent angle = T 
Vertex X = Xv 
Vertex Y = Yv 

Control Point 1: 
Xcp1 = cos(T)*r 
Ycp1 = sin(T)*r 

Control Point 2: 
Xcp2 = cos(T)*(-r) 
Ycp2 = sin(T)*(-r) 

最後の問題は、実際curvetoといった各制御点を配置する場所でありますコマンド:

CX1 Y1 X2 Y2 X3 Y3 

X3とY3が頂点の位置を定義します。 X1 Y1とX2 Y2は制御点を定義する。 X1 Y1は頂点を入力する方法のベクトルを定義し、X2 Y2は離れる方法のベクトルを定義すると考えることができます。今、あなたは、2つの制御点を持っていることを、あなたは、これは重要な決定である

CXcp1 Ycp1 Xcp2 Ycp2 0 0 

または

CXcp2 Ycp2 Xcp1 Ycp1 0 0 

に決定する必要があります。それらを後ろに持っていくと、形はループのように見えます。この時点で、この決定がどのように行われるべきかを決めることができるはずです...

また、これは非常に簡単な解決策ですが、手描きのパスによく見える傾向があります。より良い解決策は、それをさらに進め、交差点を内側の各線分交差点の凹部に向かって移動させることができる。これはかなり困難です。

+1

コントロールポイントの計算方法の例を教えてください。 – florianguenther

+0

私はこの道を手伝ってくれる数学を追加しました – jordancpaul

+0

これはおそらく私が見た最高の答えの1つです – austinbv

2

私はその背後にあるアルゴリズムを潜んでいる、私は彼らがpath simplificationのための一つの例を持っていることがわかりましたpaperjsの例を見て、同じ問題でよ、あなたはここでそれを見ることができます:それはパスの魔女を簡素化するアルゴリズムですhttps://github.com/paperjs/paper.js/blob/master/src/path/PathFitter.js

"An algorithm for automatically fitting digitized curves"という名前の学術研究のjs版(最適化あり)です。

私はこのアルゴリズムのみを抽出しており、おそらくsvg.jsへのプラグインとして公開しています。

+0

あなたはsvg.jsでそれを実装することに慣れましたか? – Rohit

+0

申し訳ありません、いいえ:( 私は今このサイドプロジェクトに取り組んでいません。 – madcampos

1

はのは、ユーザの描画がタプルの配列である、我々はthis article

const points = [[100, 50], [50, 15], [5, 60], [10, 20], [20, 10], [30, 190], [40, 10], [50, 60], [60, 120], [70, 10], [80, 50], [90, 50], [120, 10], [150, 80], [160, 10] ] 
 

 
const lineProperties = (pointA, pointB) => { 
 
    const lengthX = pointB[0] - pointA[0] 
 
    const lengthY = pointB[1] - pointA[1] 
 
    return { 
 
    length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)), 
 
    angle: Math.atan2(lengthY, lengthX) 
 
    } 
 
} 
 

 
const controlPointCalc = (current, previous, next, reverse) => { 
 
    const c = current 
 
    const p = previous ? previous : c 
 
    const n = next ? next : c 
 
    const smoothing = 0.2 
 
    const o = lineProperties(p, n) 
 
    const rev = reverse ? Math.PI : 0 
 

 
    const x = c[0] + Math.cos(o.angle + rev) * o.length * smoothing 
 
    const y = c[1] + Math.sin(o.angle + rev) * o.length * smoothing 
 

 
    return [x, y] 
 
} 
 

 
const svgPathRender = points => {  
 
    const d = points.reduce((acc, e, i, a) => { 
 
     if (i > 0) { 
 
     const cs = controlPointCalc(a[i - 1], a[i - 2], e) 
 
     const ce = controlPointCalc(e, a[i - 1], a[i + 1], true) 
 
     return `${acc} C ${cs[0]},${cs[1]} ${ce[0]},${ce[1]} ${e[0]},${e[1]}` 
 
     } else { 
 
     return `${acc} M ${e[0]},${e[1]}` 
 
     } 
 
    },'') 
 

 
    return `<path d="${d}" fill="none" stroke="black" />` 
 
} 
 

 
const svg = document.querySelector('.svg') 
 

 
svg.innerHTML = svgPathRender(points)
<svg viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" class="svg"> 
 
</svg>

詳細な説明のような何かを行うことができます想像してみましょう。

関連する問題