I started to build a widget that uses svg asset that is a soccer court. I was working with regular 2d rectangle so far and it went well. However i wanted to replace that asset with this one:
I started to prototype on how to calculate the ball position in this kind of svg and its not going well. I guess that what i need is some kind of conversion from regular 2d rectangle model to something else that would account trapeze figure.
Maybe someone could help with understanding how its done. Lets say i have following coords {x: 0.2, y: 0.2}
which means i have to put the ball in 20% of width of court and 20% of its height. How do i do in this example?
EDIT #1
I read an answer posted by MBo and i made effort to rewrite delphi code to JavaScript.I dont know delphi at all but i think it went well, however after trying code out i bumped onto couple of problems:
-
trapeze is reversed (shorter horizotal line on the bottom), i attempted to fix it but without success, after couple of tries i had this as i wanted but then
0.2, 0.2
coord showed up on the bottom instead of closer to the top. -
i am not sure if the calculation works correctly in general, center coord seems odly gravitating towards bottom (at least it is my visual impresion)
-
I attempted to fix reversed trapeze problem by playing with
YShift = Hg / 4;
but it causes variety of issues. Would like to know how this works exactly -
From what i understand, this script works in a way that you specify longer horizontal line
Wd
and heightHg
and this produces a trapeze for you, is that correct?
this is working code:
function CalcAxialSymPersp(SrcWdt, SrcHgt, DstWdt, RBX, RBY, RTX, RTY /* Integer */) {
var A, H, E; /* Double */
A = (2 * RBX - DstWdt) / SrcWdt;
H = (A * SrcWdt/ (2 * RTX - DstWdt) - 1) / SrcHgt;
E = (RTY * (H * SrcHgt + 1) - RBY) / SrcHgt;
return { A, H, E };
}
function PerspMap(SrcWdt, DstHgt, DstWdt, RBY /* Integer */, A, H, E /* Double */, PSrc /* TPoint*/) {
var PPersp = {}; /* TPoint */
PPersp.X = Math.round(DstWdt / 2 + A * (PSrc.X - SrcWdt/2) / (H * PSrc.Y + 1));
//PPersp.Y = Math.round((RBY + E * PSrc.Y) / (H * PSrc.Y + 1));
PPersp.Y = DstHgt - Math.round((RBY + E * PSrc.Y) / (H * PSrc.Y + 1));
return PPersp;
}
var Wd, Hg, YShift /* Integer */, A, H, E /* Double */, Pts = []; /* array[0..3] of TPoint */;
//XPersp = XPCenter + A * (X - XCenter) / (H * Y + 1)
//YPersp = (YShift + E * Y) / (H * Y + 1)
Wd = 600; // width of source
Hg = 200; // height of source
YShift = Hg / 4;
var { A, H, E } = CalcAxialSymPersp(Wd, Hg, Wd, Wd * 9 / 10, YShift, Wd * 8 / 10, Hg * 3 / 4);
Pts.push( PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: Wd, Y: 0 }) );
Pts.push( PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: Wd, Y: Hg }) );
Pts.push( PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: 0, Y: Hg }) );
Pts.push( PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: 0, Y: 0 }) );
//map and draw central point
var center = PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: Wd / 2, Y: Hg - (Hg / 2) });
document.querySelector('#center').setAttribute("cx", center.X);
document.querySelector('#center').setAttribute("cy", center.Y);
//map and draw point at (0.2,0.2)
var custom_coord = PerspMap(Wd, Hg, Wd, YShift, A, H, E, { X: Wd * 2 / 10, Y: Hg - (Hg * 2 / 10) });
document.querySelector('#custom-coord').setAttribute("cx", custom_coord.X);
document.querySelector('#custom-coord').setAttribute("cy", custom_coord.Y);
// draw a trapeze
document.querySelector('#trapeze').setAttribute("d", `
M ${Pts[0].X} ${Pts[0].Y}
L ${Pts[1].X} ${Pts[1].Y}
L ${Pts[2].X} ${Pts[2].Y}
L ${Pts[3].X} ${Pts[3].Y}
Z
`);
/* helper */ document.querySelector('#NW-SE').setAttribute('d', `M${Pts[0].X} ${Pts[0].Y} L${Pts[2].X} ${Pts[2].Y}`);
/* helper */ document.querySelector('#SW-NE').setAttribute('d', `M${Pts[3].X} ${Pts[3].Y} L${Pts[1].X} ${Pts[1].Y}`);
body {
margin:2px;
}
svg {
width:600px;
height:200px;
background:#ccc;
border:solid 1px #000;
}
path {
stroke:#000;
fill:none;
}
<div id="wrap">
<svg>
<path id="trapeze"></path>
<circle id="center" r="3"></circle>
<circle fill="red" id="custom-coord" r="3"></circle>
<path id="NW-SE"></path>
<path id="SW-NE"></path>
</svg>
</div>
EDIT #2
I updated demo snippet, it seems to work in some way, the only problem currently i have is that if i specify
Wd = 600; // width of source
Hg = 200; // height of source
the actuall trapeze is smaller (has less width and height),
also in some weird way manipulating this line:
YShift = Hg / 4;
changes the actuall height of trapeze.
its just then difficult to implement, as if i have been given svg court with certain size i need to be able to provide the actuall size to the function so then coords calculations will be accurate.
Lets say that i will be given court where i know 4 corners and based on that i need to be able to calculate coords. This implementation from my demo snippet, doesnt o it unfortunately.
Anyone could help alter the code or provide better implementation?
from convert regular 2d rectangle coords to trapeze
No comments:
Post a Comment