//o = vNewBisect (a, b)
//  Array o
//  Array a
//  Array b
function vNewBisect (a, b) {
return [(a[0] + b[0]) * 0.5,
(a[1] + b[1]) * 0.5];
}

//------------------------------------------------------------------------
//centroid 三角形の重心
//  中線(頂点と辺の中点を結ぶ直線)の交点
//  G=(A+B+C)/3

//a = vCentroid (a, b, c)
//  Array a
//  Array b
//  Array c
function vCentroid (a, b, c) {
a[0] = (a[0] + b[0] + c[0]) * ONE_3;
a[1] = (a[1] + b[1] + c[1]) * ONE_3;
return a;
}

//o = vLetCentroid (o, a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vLetCentroid (o, a, b, c) {
o[0] = (a[0] + b[0] + c[0]) * ONE_3;
o[1] = (a[1] + b[1] + c[1]) * ONE_3;
return o;
}

//o = vNewCentroid (a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vNewCentroid (a, b, c) {
return [(a[0] + b[0] + c[0]) * ONE_3,
(a[1] + b[1] + c[1]) * ONE_3];
}

//------------------------------------------------------------------------
//circumcenter 三角形の外心
//  外接円の中心。辺の垂直二等分線の交点
//  O=(sin(2*A)*A+sin(2*B)*B+sin(2*C)*C)/(sin(2*A)+sin(2*B)+sin(2*C))

//a = vCircumcenter (a, b, c)
//  Array a
//  Array b
//  Array c
function vCircumcenter (a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let sin2a = 2 * sqrt (1 - cosa * cosa) * cosa;  //double
let sin2b = 2 * sqrt (1 - cosb * cosb) * cosb;  //double
let sin2c = 2 * sqrt (1 - cosc * cosc) * cosc;  //double
let d = sin2a + sin2b + sin2c;  //double
a[0] = (sin2a * a[0] + sin2b * b[0] + sin2c * c[0]) / d;
a[1] = (sin2a * a[1] + sin2b * b[1] + sin2c * c[1]) / d;
return a;
}

//o = vLetCircumcenter (o, a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vLetCircumcenter (o, a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let sin2a = 2 * sqrt (1 - cosa * cosa) * cosa;  //double
let sin2b = 2 * sqrt (1 - cosb * cosb) * cosb;  //double
let sin2c = 2 * sqrt (1 - cosc * cosc) * cosc;  //double
let d = sin2a + sin2b + sin2c;  //double
o[0] = (sin2a * a[0] + sin2b * b[0] + sin2c * c[0]) / d;
o[1] = (sin2a * a[1] + sin2b * b[1] + sin2c * c[1]) / d;
return o;
}

//o = vNewCircumcenter (a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vNewCircumcenter (a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let sin2a = 2 * sqrt (1 - cosa * cosa) * cosa;  //double
let sin2b = 2 * sqrt (1 - cosb * cosb) * cosb;  //double
let sin2c = 2 * sqrt (1 - cosc * cosc) * cosc;  //double
let d = sin2a + sin2b + sin2c;  //double
return [(sin2a * a[0] + sin2b * b[0] + sin2c * c[0]) / d,
(sin2a * a[1] + sin2b * b[1] + sin2c * c[1]) / d];
}

//------------------------------------------------------------------------
//copy コピー
//  a

//o = vLetCopy (o, a)
//  Array o
//  Array a
function vLetCopy (o, a) {
o[0] = a[0];
o[1] = a[1];
return o;
}

//o = vNewCopy (a)
//  Array o
//  Array a
function vNewCopy (a) {
return a.concat ();
}

//------------------------------------------------------------------------
//cos angle なす角のコサイン
//  cos(t)=(a.b)/(|a|*|b|)
//  ゼロベクトルは不可

//cost = vCosAngle (a, b)
//  double cost
//  Array a
//  Array b
function vCosAngle (a, b) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
return (ax * bx + ay * by) / (hypot2 (ax, ay) * hypot2 (bx, by));
}

//------------------------------------------------------------------------
//cos angle a 三角形abcの角aのコサイン
//  辺abと辺acのなす角のコサイン

//cost = vCosAngleA (a, b, c)
//  double cost
//  Array a
//  Array b
//  Array c
function vCosAngleA (a, b, c) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
let cx = c[0], cy = c[1];  //double
bx -= ax;
by -= ay;
cx -= ax;
cy -= ay;
return (bx * cx + by * cy) / (hypot2 (bx, by) * hypot2 (cx, cy));
}

//------------------------------------------------------------------------
//counterclockwise 反時計回り(左回り)か
//  0<sならば反時計回り(左回り)、s<0ならば時計回り(右回り)
//
//  直線ab上の点p
//    (px,py)=(ax+(bx-ax)*s,ay+(by-ay)*s)
//  点pを通り直線abと直交する直線上の点c
//    (cx,cy)=(px+(by-ay)*t,py-(bx-ax)*t)
//           =(ax+(bx-ax)*s+(by-ay)*t,ay+(by-ay)*s-(bx-ax)*t)
//    s=((ax-bx)*(ax-cx)+(ay-by)*(ay-cy))/((ax-bx)^2+(ay-by)^2)
//    t=((by-ay)*cx-(bx-ax)*cy-ax*by+ay*bx)/((ax-bx)^2+(ay-by)^2)
//  tの符号が正ならば左回り、負ならば右回り

//s = vCounterclockwise (a, b, c)
//  double s
//  Array a
//  Array b
//  Array c
function vCounterclockwise (a, b, c) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
let cx = c[0], cy = c[1];  //double
return (by - ay) * cx - (bx - ax) * cy - ax * by + ay * bx;
}

//------------------------------------------------------------------------
//distance 点と点の距離
//  |b-a|

//s = vDistance (a, b)
//  double s
//  Array a
//  Array b
function vDistance (a, b) {
return hypot2 (b[0] - a[0], b[1] - a[1]);
}

//------------------------------------------------------------------------
//distance2 点と点の距離の2乗
//  |b-a|^2

//s = vDistance2 (a, b)
//  double s
//  Array a
//  Array b
function vDistance2 (a, b) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
bx -= ax;
by -= ay;
return bx * bx + by * by;
}

//------------------------------------------------------------------------
//dot ドット積(内積,スカラー積)
//  a.b=|a|*|b|*cos(angle(a,b))

//s = vDot (a, b)
//  double s
//  Array a
//  Array b
function vDot (a, b) {
return a[0] * b[0] + a[1] * b[1];
}

//------------------------------------------------------------------------
//hat 単位ベクトル化
//  a/|a|
//  ゼロベクトルは不可

//a = vHat (a)
//  Array a
function vHat (a) {
let ax = a[0], ay = a[1];  //double
let s = hypot2 (ax, ay);  //double
a[0] = ax / s;
a[1] = ay / s;
return a;
}

//o = vLetHat (o, a)
//  Array o
//  Array a
function vLetHat (o, a) {
let ax = a[0], ay = a[1];  //double
let s = hypot2 (ax, ay);  //double
o[0] = ax / s;
o[1] = ay / s;
return o;
}

//o = vNewHat (a)
//  Array o
//  Array a
function vNewHat (a) {
let ax = a[0], ay = a[1];  //double
let s = hypot2 (ax, ay);  //double
return [ax / s,
ay / s];
}

//------------------------------------------------------------------------
//height 三角形abcの高さ
//  点aと直線bcの距離。点aから直線bcへ下ろした垂線の長さ

//s = vHeight (a, b, c)
//  double s
//  Array a
//  Array b
//  Array c
function vHeight (a, b, c) {
return vDistance (a, vNewPerpendicularFoot (a, b, c));
}

//------------------------------------------------------------------------
//incenter 三角形の内心
//  内接円の中心。角の二等分線の交点
//  I=(a*A+b*B+c*C)/(a+b+c)

//a = vIncenter (a, b, c)
//  Array a
//  Array b
//  Array c
function vIncenter (a, b, c) {
let la = wDistance (b, c);  //double
let lb = wDistance (c, a);  //double
let lc = wDistance (a, b);  //double
let d = la + lb + lc;  //double
a[0] = (la * a[0] + lb * b[0] + lc * c[0]) / d;
a[1] = (la * a[1] + lb * b[1] + lc * c[1]) / d;
return a;
}

//o = vLetIncenter (o, a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vLetIncenter (o, a, b, c) {
let la = wDistance (b, c);  //double
let lb = wDistance (c, a);  //double
let lc = wDistance (a, b);  //double
let d = la + lb + lc;  //double
o[0] = (la * a[0] + lb * b[0] + lc * c[0]) / d;
o[1] = (la * a[1] + lb * b[1] + lc * c[1]) / d;
return o;
}

//o = vNewIncenter (a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vNewIncenter (a, b, c) {
let la = wDistance (b, c);  //double
let lb = wDistance (c, a);  //double
let lc = wDistance (a, b);  //double
let d = la + lb + lc;  //double
return [(la * a[0] + lb * b[0] + lc * c[0]) / d,
(la * a[1] + lb * b[1] + lc * c[1]) / d];
}

//------------------------------------------------------------------------
//norm 長さ(ノルム)
//  |a|=sqrt(a.a)

//s = vNorm (a)
//  double s
//  Array a
function vNorm (a) {
return hypot2 (a[0], a[1]);
}

//------------------------------------------------------------------------
//norm2 長さ(ノルム)の2乗
//  |a|^2=a.a

//s = vNorm2 (a)
//  double s
//  Array a
function vNorm2 (a) {
let ax = a[0], ay = a[1];  //double
return ax * ax + ay * ay;
}

//------------------------------------------------------------------------
//one 1ベクトル
//  1

//o = vLetOneX (o)
//  Array o
function vLetOneX (o) {
o[0] = 1;
o[1] = 0;
return o;
}

//o = vNewOneX ()
//  Array o
function vNewOneX () {
return [1,
0];
}

//o = vLetOneY (o)
//  Array o
function vLetOneY (o) {
o[0] = 0;
o[1] = 1;
return o;
}

//o = vNewOneY ()
//  Array o
function vNewOneY () {
return [0,
1];
}

//------------------------------------------------------------------------
//orthocenter 三角形の垂心
//  頂点から辺に下ろした垂線の交点
//  H=(tan(A)*A+tan(B)*B+tan(C)*C)/(tan(A)+tan(B)+tan(C))

//a = vOrthocenter (a, b, c)
//  Array a
//  Array b
//  Array c
function vOrthocenter (a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let tana = sqrt (1 - cosa * cosa) / cosa;  //double
let tanb = sqrt (1 - cosb * cosb) / cosb;  //double
let tanc = sqrt (1 - cosc * cosc) / cosc;  //double
let d = tana + tanb + tanc;  //double
a[0] = (tana * a[0] + tanb * b[0] + tanc * c[0]) / d;
a[1] = (tana * a[1] + tanb * b[1] + tanc * c[1]) / d;
return a;
}

//o = vLetOrthocenter (o, a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vLetOrthocenter (o, a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let tana = sqrt (1 - cosa * cosa) / cosa;  //double
let tanb = sqrt (1 - cosb * cosb) / cosb;  //double
let tanc = sqrt (1 - cosc * cosc) / cosc;  //double
let d = tana + tanb + tanc;  //double
o[0] = (tana * a[0] + tanb * b[0] + tanc * c[0]) / d;
o[1] = (tana * a[1] + tanb * b[1] + tanc * c[1]) / d;
return o;
}

//o = vNewOrthocenter (a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vNewOrthocenter (a, b, c) {
let cosa = vCosAngleA (a, b, c);  //double
let cosb = vCosAngleA (b, c, a);  //double
let cosc = vCosAngleA (c, a, b);  //double
let tana = sqrt (1 - cosa * cosa) / cosa;  //double
let tanb = sqrt (1 - cosb * cosb) / cosb;  //double
let tanc = sqrt (1 - cosc * cosc) / cosc;  //double
let d = tana + tanb + tanc;  //double
return [(tana * a[0] + tanb * b[0] + tanc * c[0]) / d,
(tana * a[1] + tanb * b[1] + tanc * c[1]) / d];
}

//------------------------------------------------------------------------
//perpendicular foot 垂線の足
//  点aから直線bcに下ろした垂線の足d
//  平面
//    直線bc上の点dを通って直線bcと直交する直線上の点a
//    (dx,dy)=(bx+(cx-bx)*s,by+(cy-by)*s)
//    (cx-bx)*(ax-dx)+(cy-by)*(ay-dy)=0
//    (cx-bx)*(ax-(bx+(cx-bx)*s))+(cy-by)*(ay-(by+(cy-by)*s))=0
//    s=((ax-bx)*(cx-bx)+(ay-by)*(cy-by))/((cx-bx)^2+(cy-by)^2)
//  空間
//    直線bc上の点dを通って直線bcと直交する平面上の点a
//    (dx,dy,dz)=(bx+(cx-bx)*s,by+(cy-by)*s,bz+(cz-bz)*s)
//    (cx-bx)*(ax-dx)+(cy-by)*(ay-dy)+(cz-bz)*(az-dz)=0
//    (cx-bx)*(ax-(bx+(cx-bx)*s))+(cy-by)*(ay-(by+(cy-by)*s))+(cz-bz)*(az-(bz+(cz-bz)*s))=0
//    s=((ax-bx)*(cx-bx)+(ay-by)*(cy-by)+(az-bz)*(cz-bz))/((cx-bx)^2+(cy-by)^2+(cz-bz)^2)

//a = vPerpendicularFoot (a, b, c)
//  Array a
//  Array b
//  Array c
function vPerpendicularFoot (a, b, c) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
let cx = c[0], cy = c[1];  //double
let s = (((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) /
((cx - bx) * (cx - bx) + (cy - by) * (cy - by)));  //double
a[0] = bx + (cx - bx) * s;
a[1] = by + (cy - by) * s;
return a;
}

//o = vLetPerpendicularFoot (o, a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vLetPerpendicularFoot (o, a, b, c) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
let cx = c[0], cy = c[1];  //double
let s = (((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) /
((cx - bx) * (cx - bx) + (cy - by) * (cy - by)));  //double
o[0] = bx + (cx - bx) * s;
o[1] = by + (cy - by) * s;
return o;
}

//o = vNewPerpendicularFoot (a, b, c)
//  Array o
//  Array a
//  Array b
//  Array c
function vNewPerpendicularFoot (a, b, c) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
let cx = c[0], cy = c[1];  //double
let s = (((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) /
((cx - bx) * (cx - bx) + (cy - by) * (cy - by)));  //double
return [bx + (cx - bx) * s,
by + (cy - by) * s];
}

//------------------------------------------------------------------------
//reverse 逆向きベクトル
//  -a

//a = vReverse (a)
//  Array a
function vReverse (a) {
a[0] = -a[0];
a[1] = -a[1];
return a;
}

//o = vLetReverse (o, a)
//  Array o
//  Array a
function vLetReverse (o, a) {
o[0] = -a[0];
o[1] = -a[1];
return o;
}

//o = vNewReverse (a)
//  Array o
//  Array a
function vNewReverse (a) {
return [-a[0],
-a[1]];
}

//------------------------------------------------------------------------
//rotate 回転(+x→+y)
//
//    [cos(t) -sin(t) 0]   [x]   [cos(t)*x-sin(t)*y]
//    [sin(t)  cos(t) 0] * [y] = [sin(t)*x+cos(t)*y]
//    [  0       0    1]   [1]   [        1        ]
//

//a = vRotate (a, t)
//  Array a
//  double t
function vRotate (a, t) {
let ax = a[0], ay = a[1];  //double
let c = cos (t), s = sin (t);  //double
a[0] = c * ax - s * ay;
a[1] = s * ax + c * ay;
return a;
}

//o = vLetRotate (o, a, t)
//  Array o
//  Array a
//  double t
function vLetRotate (o, a, t) {
let ax = a[0], ay = a[1];  //double
let c = cos (t), s = sin (t);  //double
o[0] = c * ax - s * ay;
o[1] = s * ax + c * ay;
return o;
}

//o = vNewRotate (a, t)
//  Array o
//  Array a
//  double t
function vNewRotate (a, t) {
let ax = a[0], ay = a[1];  //double
let c = cos (t), s = sin (t);  //double
return [c * ax - s * ay,
s * ax + c * ay];
}

//------------------------------------------------------------------------
//scalar スカラーベクトル
//  s

//o = vLetScalarX (o, s)
//  Array o
//  double s
function vLetScalarX (o, s) {
o[0] = s;
o[1] = 0;
return o;
}

//o = vNewScalarX (s)
//  Array o
//  double s
function vNewScalarX (s) {
return [s,
0];
}

//o = vLetScalarY (o, s)
//  Array o
//  double s
function vLetScalarY (o, s) {
o[0] = 0;
o[1] = s;
return o;
}

//o = vNewScalarY (s)
//  Array o
//  double s
function vNewScalarY (s) {
return [0,
s];
}

//------------------------------------------------------------------------
//scale 拡大縮小
//
//    [p 0 0]   [x]   [p*x]
//    [0 q 0] * [y] = [q*y]
//    [0 0 1]   [1]   [ 1 ]
//
//  s*a

//a = vScaleS (a, s)
//  Array a
//  double s
function vScaleS (a, s) {
a[0] *= s;
a[1] *= s;
return a;
}

//o = vLetScaleS (o, a, s)
//  Array o
//  Array a
//  double s
function vLetScaleS (o, a, s) {
o[0] = a[0] * s;
o[1] = a[1] * s;
return o;
}

//o = vNewScaleS (a, s)
//  Array o
//  Array a
//  double s
function vNewScaleS (a, s) {
return [a[0] * s,
a[1] * s];
}

//a = vScaleV (a, v)
//  Array a
//  Array v
function vScaleV (a, v) {
a[0] *= v[0];
a[1] *= v[1];
return a;
}

//o = vLetScaleV (o, a, v)
//  Array o
//  Array a
//  Array v
function vLetScaleV (o, a, v) {
o[0] = a[0] * v[0];
o[1] = a[1] * v[1];
return o;
}

//o = vNewScaleV (a, v)
//  Array o
//  Array a
//  Array v
function vNewScaleV (a, v) {
return [a[0] * v[0],
a[1] * v[1]];
}

//a = vScaleX (a, p)
//  Array a
//  double p
function vScaleX (a, p) {
a[0] *= p;
return a;
}

//o = vLetScaleX (o, a, p)
//  Array o
//  Array a
//  double p
function vLetScaleX (o, a, p) {
o[0] = a[0] * p;
o[1] = a[1];
return o;
}

//o = vNewScaleX (a, p)
//  Array o
//  Array a
//  double p
function vNewScaleX (a, p) {
return [a[0] * p,
a[1]];
}

//a = vScaleY (a, q)
//  Array a
//  double q
function vScaleY (a, q) {
a[1] *= q;
return a;
}

//o = vLetScaleY (o, a, q)
//  Array o
//  Array a
//  double q
function vLetScaleY (o, a, q) {
o[0] = a[0];
o[1] = a[1] * q;
return o;
}

//o = vNewScaleY (a, q)
//  Array o
//  Array a
//  double q
function vNewScaleY (a, q) {
return [a[0],
a[1] * q];
}

//a = vScaleXY (a, p, q)
//  Array a
//  double p
//  double q
function vScaleXY (a, p, q) {
a[0] *= p;
a[1] *= q;
return a;
}

//o = vLetScaleXY (o, a, p, q)
//  Array o
//  Array a
//  double p
//  double q
function vLetScaleXY (o, a, p, q) {
o[0] = a[0] * p;
o[1] = a[1] * q;
return o;
}

//o = vNewScaleXY (a, p, q)
//  Array o
//  Array a
//  double p
//  double q
function vNewScaleXY (a, p, q) {
return [a[0] * p,
a[1] * q];
}

//------------------------------------------------------------------------
//stretch 長さ(ノルム)変更
//  hat(a)*(|a|*s+t)=a/|a|*(|a|*s+t)=a*(s+t/|a|)
//  ゼロベクトルは不可

//a = vStretch (a, s, t)
//  Array a
//  double s
//  double t
function vStretch (a, s, t) {
let ax = a[0], ay = a[1];  //double
s += t / hypot2 (ax, ay);
a[0] = ax * s;
a[1] = ay * s;
return a;
}

//o = vLetStretch (o, a, s, t)
//  Array o
//  Array a
//  double s
//  double t
function vLetStretch (o, a, s, t) {
let ax = a[0], ay = a[1];  //double
s += t / hypot2 (ax, ay);
o[0] = ax * s;
o[1] = ay * s;
return o;
}

//o = vNewStretch (a, s, t)
//  Array o
//  Array a
//  double s
//  double t
function vNewStretch (a, s, t) {
let ax = a[0], ay = a[1];  //double
s += t / hypot2 (ax, ay);
return [ax * s,
ay * s];
}

//------------------------------------------------------------------------
//stretch from 距離変更
//  hat(a-b)*(|a-b|*s+t)+b=(a-b)/|a-b|*(|a-b|*s+t)+b=(a-b)*(s+t/|a-b|)+b
//  a==bは不可

//a = vStretchFrom (a, s, t, b)
//  Array a
//  double s
//  double t
//  Array b
function vStretchFrom (a, s, t, b) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
ax -= bx;
ay -= by;
s += t / hypot2 (ax, ay);
a[0] = ax * s + bx;
a[1] = ay * s + by;
return a;
}

//o = vLetStretchFrom (o, a, s, t, b)
//  Array o
//  Array a
//  double s
//  double t
//  Array b
function vLetStretchFrom (o, a, s, t, b) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
ax -= bx;
ay -= by;
s += t / hypot2 (ax, ay);
o[0] = ax * s + bx;
o[1] = ay * s + by;
return o;
}

//o = vNewStretchFrom (a, s, t, b)
//  Array o
//  Array a
//  double s
//  double t
//  Array b
function vNewStretchFrom (a, s, t, b) {
let ax = a[0], ay = a[1];  //double
let bx = b[0], by = b[1];  //double
ax -= bx;
ay -= by;
s += t / hypot2 (ax, ay);
return [ax * s + bx,
ay * s + by];
}

//------------------------------------------------------------------------
//subtract 減算
//
//    [1 0 -d]   [x]   [x-d]
//    [0 1 -e] * [y] = [y-e]
//    [0 0  1]   [1]   [ 1 ]
//
//  a-b

//a = vSubtractV (a, b)
//  Array a
//  Array b
function vSubtractV (a, b) {
a[0] -= b[0];
a[1] -= b[1];
return a;
}

//o = vLetSubtractV (o, a, b)
//  Array o
//  Array a
//  Array b
function vLetSubtractV (o, a, b) {
o[0] = a[0] - b[0];
o[1] = a[1] - b[1];
return o;
}

//o = vNewSubtractV (a, b)
//  Array o
//  Array a
//  Array b
function vNewSubtractV (a, b) {
return [a[0] - b[0],
a[1] - b[1]];
}

//a = vSubtractX (a, d)
//  Array a
//  double d
function vSubtractX (a, d) {
a[0] -= d;
return a;
}

//o = vLetSubtractX (o, a, d)
//  Array o
//  Array a
//  double d
function vLetSubtractX (o, a, d) {
o[0] = a[0] - d;
o[1] = a[1];
return o;
}

//o = vNewSubtractX (a, d)
//  Array o
//  Array a
//  double d
function vNewSubtractX (a, d) {
return [a[0] - d,
a[1]];
}

//a = vSubtractY (a, e)
//  Array a
//  double e
function vSubtractY (a, e) {
a[1] -= e;
return a;
}

//o = vLetSubtractY (o, a, e)
//  Array o
//  Array a
//  double e
function vLetSubtractY (o, a, e) {
o[0] = a[0];
o[1] = a[1] - e;
return o;
}

//o = vNewSubtractY (a, e)
//  Array o
//  Array a
//  double e
function vNewSubtractY (a, e) {
return [a[0],
a[1] - e];
}

//a = vSubtractXY (a, d, e)
//  Array a
//  double d
//  double e
function vSubtractXY (a, d, e) {
a[0] -= d;
a[1] -= e;
return a;
}

//o = vLetSubtractXY (o, a, d, e)
//  Array o
//  Array a
//  double d
//  double e
function vLetSubtractXY (o, a, d, e) {
o[0] = a[0] - d;
o[1] = a[1] - e;
return o;
}

//o = vNewSubtractXY (a, d, e)
//  Array o
//  Array a
//  double d
//  double e
function vNewSubtractXY (a, d, e) {
return [a[0] - d,
a[1] - e];
}

//------------------------------------------------------------------------
//transform 変換
//
//    [m11 m12 m13]   [x]   [m11*x+m12*y+m13]
//    [m21 m22 m23] * [y] = [m21*x+m22*y+m23]
//    [ 0   0   1 ]   [1]   [       1       ]
//
//  m*a
//  引数の順序に注意

//a = vTransform (a, m)
//  Array a
//  Array m
function vTransform (a, m) {
let ax = a[0], ay = a[1];  //double
a[0] = m[0] * ax + m[1] * ay + m[2];
a[1] = m[3] * ax + m[4] * ay + m[5];
return a;
}

//o = vLetTransform (o, a, m)
//  Array o
//  Array a
//  Array m
function vLetTransform (o, a, m) {
let ax = a[0], ay = a[1];  //double
o[0] = m[0] * ax + m[1] * ay + m[2];