Processing 3, 815 833 835 876 879 bytes
Saved two bytes thanks to @ZacharyT by removing unnecessary parentheses
void settings(){size(600,600);}int i,w,x,n;float l,d,t,a,f,g,m,R,U;float[][]N,T;float[]S,p;void s(float[][]t){N=new float[t.length+1][2];N[0][0]=N[0][1]=i=0;for(float[]q:t)N[++i]=q;translate(w=300,w);noFill();pushMatrix();f(N,0,-w,w,1,0);popMatrix();f(N,0,-w,w,0,0);}float p(float a,float b){for(a+=PI*4;a>b;)a-=PI*2;return a;}void f(float[][]P,float x,float y,float L,int c,int I){l=2*PI;d=i=0;S=null;for(;i<P.length;i++){float[]p=P[i];g=atan2(y,x);m=atan2(p[1],p[0]);if(p(f=(c*2-1)*(g-m),0)<l&(t=dist(0,0,p[0],p[1]))<=L&I!=i){l=p(f,0);S=new float[]{g,m};d=t;n=i;}}if(S==null)ellipse(0,0,2*(L-d),2*(L-d));else{arc(0,0,L*2,L*2,p(S[c],S[1-c]),S[1-c]);R=cos(a=S[1]);U=sin(a);translate(d*R,d*U);T=new float[P.length][2];for(int i=0;i<T.length;T[i][1]=P[i][1]-d*U,i++)T[i][0]=P[i][0]-d*R;f(T,(L-d)*R,(L-d)*U,L-d,c,n);}}
Run this program like so:
void setup() {
s(new float[][]{{0,100},{100,100},{-200,100},{-100,-50}});
}
(the function s
takes in a float[][]
). This is essentially testcase #3, but multiplied by 100 to fit the window.
Several things to note:
- the program does NOT draw poles
- the images appear flipped upside-down because in Processing's coordinate system, the positive y-axis goes down
- because Processing uses floats, the calculations are not very accurate, so you might see this in the images. I have asked the OP if these floating-point error matter.
- the size of the window is 600 pixels by 600 pixels
- very small input coordinates will bork the program because the stack
pushMatrix()
and popMatrix()
operate on can only hold 32 matrices.
- the dog starts at (0, -300) and the chain starts at 300 pixels long
- the images below have been minified for convenience
Sample output for the above testcase.
If you want to see the prettified output, add this line right after the translate(w,w);
in function s
.
background(-1);scale(1,-1);fill(255,0,0);ellipse(0,0,25,25);fill(0);for(float[]q:N)ellipse(q[0],q[1],25,25);
And this gives us this result:
Ungolfed f()
and explanation
(contains debug code as well)
void f(float[][]points, float x, float y, float len, int c, int pindex) {
print(asd+++")");
float closest = 2*PI;
float d=0,t;
float[]stuff = null;
int index = 0;
for(int i=0;i<points.length;i++) {
if(pindex != i) {
float[]p = points[i];
float originAngle = atan2(y, x);
float tempAngle = atan2(p[1], p[0]);
//println(x,y,p[0],p[1]);
float diff = c<1?tempAngle-originAngle:originAngle-tempAngle;
println("@\t"+i+"; x=\t"+x+"; y=\t"+y+"; tx=\t"+p[0]+"; ty=\t",p[1], diff, originAngle, tempAngle);
if(p(diff) < closest && (t=dist(0,0,p[0],p[1])) < len) {
println("+1");
closest = p(diff);
stuff = new float[]{originAngle, tempAngle};
d=t;
index = i;
}
}
}
if(stuff == null) {
ellipse(0,0,2*(len-d),2*(len-d));
println("mayday");
} else {
println("d angles",d,p(stuff[c],stuff[1-c],c), stuff[1-c]);
//println(points[0]);
arc(0, 0, len*2, len*2, p(stuff[c],stuff[1-c],c), stuff[1-c]);
float angle = stuff[1];
translate(d*cos(angle), d*sin(angle));
println("Translated", d*cos(angle), d*sin(angle));
println("angle",angle);
float[][]temp=new float[points.length][2];
for(int i=0;i<temp.length;i++){
temp[i][0]=points[i][0]-d*cos(angle);
temp[i][1]=points[i][1]-d*sin(angle);
println(temp[i]);
}
println(d*sin(angle));
pushMatrix();
println();
f(temp, (len-d)*cos(angle), (len-d)*sin(angle), (len-d), c, index);
popMatrix();
//f(temp, (len-d)*cos(angle), (len-d)*sin(angle), (len-d), 0, index);
}
}
To put it shortly, the program sends two "seekers", one goes anti-clockwise and the other clockwise. Each of these seekers finds the closest pole and draws an arc to it if the chain is long enough, other wise it draws a circle. Once it draws an arc, it sends another seeker to that pole and the process continues. f()
contains the process of each seeker. A more detailed explanation will come as soon as I golf this more.
What is the output for
{0,-.5}
? – user41805 – 2017-06-24T12:58:03.290@KritixiLithos Its the output of
{0,.5}
flipped vertically without the largest circle. The dog essentially starts caught on the second pole. – Post Rock Garf Hunter – 2017-06-24T13:02:19.713As a result of floating-point issues, my program draws a circle around (1,1) in the last testcase (the string length is 99.99999). Is this okay? – user41805 – 2017-06-25T06:23:27.890
The dog runs both clockwise and counter-clockwise, but from a fixed point? – user202729 – 2017-06-25T06:34:24.123
3"The sun is rising the space on the floor of my attic illuminated by the window is shrinking giving me less and less space to write my code" +1 just for this – Leo – 2017-06-25T08:28:20.167