Przetwarzanie 3, 815 833 835 876 879 bajtów
Zaoszczędź dwa bajty dzięki @ZacharyT, usuwając niepotrzebne nawiasy
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);}}
Uruchom ten program tak:
void setup() {
s(new float[][]{{0,100},{100,100},{-200,100},{-100,-50}});
}
(funkcja s
przyjmuje a float[][]
). Jest to zasadniczo przypadek testowy nr 3, ale pomnożony przez 100 w celu dopasowania do okna.
Kilka rzeczy do zapamiętania:
- program NIE rysuje biegunów
- obrazy wydają się odwrócone do góry nogami, ponieważ w układzie współrzędnych Przetwarzania dodatnia oś y zmniejsza się
- ponieważ Przetwarzanie używa liczb zmiennoprzecinkowych, obliczenia nie są bardzo dokładne, więc możesz to zobaczyć na obrazach. Zapytałem OP, czy te zmiennoprzecinkowe błędy mają znaczenie.
- rozmiar okna wynosi 600 na 600 pikseli
- bardzo małe współrzędne wejściowe rozbijają program, ponieważ stos
pushMatrix()
i popMatrix()
operacja mogą pomieścić tylko 32 macierze.
- pies zaczyna się od (0, -300), a łańcuch zaczyna się od 300 pikseli
- poniższe zdjęcia zostały zminimalizowane dla wygody
Przykładowe dane wyjściowe dla powyższej skrzynki testowej.
Jeśli chcesz zobaczyć upiększone wyjście, dodaj ten wiersz zaraz po translate(w,w);
funkcji in 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);
A to daje nam ten wynik:
Bez golfa f()
i wyjaśnienia
(zawiera również kod debugowania)
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);
}
}
Krótko mówiąc, program wysyła dwóch „poszukiwaczy”, jeden idzie w lewo, a drugi w prawo. Każdy z tych poszukiwaczy znajduje najbliższy biegun i rysuje do niego łuk, jeśli łańcuch jest wystarczająco długi, w przeciwnym razie rysuje okrąg. Gdy narysuje łuk, wysyła kolejnego poszukiwacza na ten biegun i proces trwa. f()
zawiera proces każdego poszukiwacza. Bardziej szczegółowe wyjaśnienie pojawi się, gdy tylko zacznę grać w golfa.
{0,-.5}
?