การวาด Epicyclogons


22

เอพิไซคลอยด์เป็นเส้นโค้งจุดบนวงกลมทำให้เป็นมันม้วนรอบวงกลมอีก cyclogonเป็นรูปร่างจุดบนเป็นรูปเหลี่ยมปกติทำให้เป็นมันม้วนทั่วเครื่องบิน epicyclogonเป็นเส้นโค้งตรวจสอบโดยจุดบนเหลี่ยมปกติหนึ่งขณะที่มันม้วนรอบอีก

เขียนโปรแกรมที่ดึง epicyclogon ที่กำหนดr, r1, r2, n1, n2:

r = number of clockwise revolutions rolling polygon makes around stationary polygon (any real number as limited by float values) 
r1 = distance from center of stationary polygon to each of its vertices (positive real number)
r2 = distance from center of rolling polygon to each of its vertices (positive real number)
n1 = number of sides stationary polygon has (integer greater than 2)
n2 = number of sides rolling polygon has (integer greater than 2)

หมายเหตุ

  • เมื่อrเป็นลบลูกกลิ้งควรจะไปทวนเข็มนาฬิกา
  • สำหรับrการปฏิวัติหนึ่งครั้งเกิดขึ้นเมื่อเส้นที่เชื่อมต่อเซนทรอยด์ของทั้งสองรูปร่างกวาดล้างเต็ม 360 องศา rความคิดนี้จะขยายไปถึงค่าทั้งหมดของ (ดังนั้นในหนึ่งไตรมาสการปฏิวัติเส้นเชื่อมต่อเซนทรอยด์สามารถกวาดล้าง 90 องศา)
  • ข้อโต้แย้งเหล่านี้ควรมาจากบรรทัดคำสั่งหรือโปรแกรมของคุณควรแจ้งให้พวกเขาทราบ (เช่นกับ Python input())
  • r1และr2สัมพันธ์กันไม่ใช่ขนาดของภาพ ดังนั้นคุณสามารถตั้งค่า "หน่วย" หนึ่งหน่วยเป็นจำนวนพิกเซลที่แท้จริง

จุดที่คุณต้องติดตามคือหนึ่งในจุดยอดของรูปร่างที่กลิ้ง รูปร่างต้องเริ่มต้นด้วยจุดสุดยอดนี้โดยการสัมผัสจุดยอดที่อยู่กับที่และด้านที่อยู่ติดกัน:

ตัวอย่าง epicyclogon

จุดเริ่มต้นที่แน่นอนและมุมของรูปหลายเหลี่ยมแบบคงที่ไม่สำคัญ

เอาท์พุต

ผลลัพธ์ควรไปที่รูปภาพที่มีขนาดอย่างน้อย 600x600 พิกเซล (หรือบางส่วนของตัวแปรที่สามารถตั้งค่าได้มากกว่า 600) จะต้องแสดงเส้นโค้ง epicyclogon ทั้งหมดที่ระบุโดยพารามิเตอร์กรอบในภาพ

รูปวาดรูปหลายเหลี่ยมแบบกลิ้งและแบบอยู่กับที่จะต้องถูกดึง (ด้วยลูกกลิ้งในสถานะสุดท้าย) สองรูปร่างและ epicyclogon ควรเป็นสามสีที่แตกต่างกันอย่างเห็นได้ชัด

จะต้องมีวิธีที่ง่ายในการไม่วาดรูปหลายเหลี่ยม (การเปลี่ยนแปลงtrueเป็นfalseในพอเพียงของรหัส)

โปรดแสดงรูปภาพที่ส่งออกอย่างน้อย 2 รูป มันก็โอเคที่จะหดมันถ้าจำเป็น

เกณฑ์การให้คะแนน

รหัสที่สั้นที่สุดที่สร้างภาพออกที่ถูกต้องชนะ

โบนัส

  • ลบ 50 ไบต์หากเอาต์พุตเป็นภาพเคลื่อนไหว gif (หรือคล้ายกัน) ของเส้นโค้งที่วาด
  • ลบ 150 ไบต์หากคุณปล่อยn1และn2รับค่า 2 เพื่อให้รูปร่างกลายเป็นส่วนของเส้นความยาว2 * r1(หรือr2), "กลิ้ง" ซึ่งกันและกัน วิธีจัดการกับrเวลาn1และn22 ขึ้นอยู่กับคุณเนื่องจากเซนทรอยด์ไม่ได้หมุนรอบกันและกันเหมือนอย่างที่พวกเขาทำในกรณีอื่น ๆ (ไม่ใช่ "การกลิ้ง" เลยจะไม่ถือว่าเป็นการจัดการ)

เนื่องจากฉันค่อนข้างกระตือรือร้นที่จะเห็นความคิดนวนิยายเรื่องนี้ดำเนินไปด้วยดี (และไม่ได้เป็นเหมือน cakewalk) ฉันจะได้รับรางวัล 150 ค่าตอบแทนผู้ชนะ การประกวดจะสิ้นสุดในวันเดียวกันกับที่เงินรางวัลหมด

เงินรางวัลจะไม่ถูกมอบให้กับผู้ชนะหากมีความชัดเจนว่าพวกเขาเพียงแค่เขียนรหัสส่วนใหญ่จากการส่งอีกครั้ง

ฟังก์ชั่นห้องสมุดที่เกิดขึ้นแล้วในการทำเช่นนี้ (ถ้ามี) ไม่ได้รับอนุญาต

หมายเหตุ: นี่มาจากคำถามที่เหลือของฉันที่ทุกคนสามารถโพสต์ได้ฟรี แต่ถ้าไม่มีใครโพสต์พวกเขามีโอกาสที่ดีที่ฉันจะทันเวลา : P


ฉันคิดว่าทวนเข็มนาฬิกาควรเป็นค่าบวกแทน
Soham Chowdhury

3
@ShaamChowdhury ฉันคิดว่ามันแทบจะไม่สำคัญ
งานอดิเรกของ Calvin

คุณพูดถูกจริงๆ คุณมีภาพตัวอย่างหรือไม่? ฉันไม่มีเครื่องเล่น CDF
Soham Chowdhury

@ githubphagocyte ฉันเห็นประเด็นของคุณแล้ว คงที่
งานอดิเรกของ Calvin

@ MartinBüttnerไม่เข้มงวดเกินไปมันเป็นเพียงสิ่งแรกที่ฉันคิด คุณสามารถแจ้งค่าในวิธีอื่นถ้าจำเป็น
งานอดิเรกของ Calvin

คำตอบ:


3

MATLAB: 735 ไบต์ - 200 โบนัส = 535

โปรแกรมของฉันจัดการกับเคส n = 2 และวาดอนิเมชั่นตามเวลาจริง มีความแตกต่างเล็กน้อยระหว่างเวอร์ชั่น golfed และ ungolfed:

เวอร์ชันที่ไม่ได้รับการอภัยมีเพียงตัวเลือกในการบันทึกภาพเคลื่อนไหวไปยังไฟล์ 'g.gif' โดยการตั้งค่าsavegif = 1ในรหัส ปิดใช้งานตามค่าเริ่มต้นเนื่องจากอาจสร้างความรำคาญด้วยเหตุผลบางประการ:

  • การสร้างไฟล์ที่ไม่ต้องการ
  • ความล่าช้าที่เป็นไปได้
  • เกิดข้อผิดพลาดหากคุณมีจอภาพหลายจอและหน้าต่างพล็อตไม่ถูกต้อง ... การบันทึก gif ต้องลดลงในเวอร์ชัน golfed เนื่องจากใช้เวลาประมาณ 100 ไบต์เกินขนาดของโบนัส

รุ่นที่ไม่ได้รับการวาดจะวาดวงกลมบนจุดสุดยอดของผู้ติดตาม นอกจากนี้ยังสร้างเฟรมมากขึ้นและเคลื่อนที่ได้เร็วขึ้น (แม้ว่าจะสามารถปรับได้ในเวอร์ชั่น golfed โดยการเปลี่ยนตัวเลข)

ตัวอย่าง:

f(11,5,90,2,99,0) หลังจากสิ้นสุดโปรแกรม

ตัวอย่าง golfed

epic(1.3,4,2,6,6,1) ด้วยผลผลิต gif

ตัวอย่างที่ไม่ได้แต่งตัว

รหัสไม่ได้รับการตอบ

%epicyclogon animation outputs to 'g.gif' if savegif=1 as well as animating in real time

function[] = epic(r,r1,r2,n1,n2,dispPoly)

savegif = 0;  %set to 1 to write .gif

cs = @(a) [cos(a);sin(a)];
vert = @(r, n, v) r * cs(2*pi*v/n);
polyPt = @(l, s, n, r) vert(r, n, floor(l/s)) + mod(l/s,1)*(vert(r, n, floor(l/s)+1) - vert(r, n, floor(l/s)));
polyPt2 = @(i, f, n, r) vert(r, n, i) + f*(vert(r, n, i+1) - vert(r, n, i));
rotm = @(a) [cos(a) -sin(a);sin(a) cos(a)];
arrpluspt = @(a, p) a + kron(p, ones(1,length(a)));
arg = @(p) atan2(p(2), p(1));

E = 1e-9;

dispPoly = dispPoly / dispPoly;

sgn = sign(-r);
r = abs(r);

s1 = 2*r1*sin(pi/n1);
s2 = 2*r2*sin(pi/n2);

%d1 = (r1*r1 - s1*s1*.25)^.5;
d2 = (r2*r2 - s2*s2*.25)^.5;

plotmax = r1+2*r2;

astep = .05; %determines amount of frames per rotation
delay = .01; % time per frame

l = 0;

lRem = 0;
lr = 0;

P1 = vert(r1, n1, 1:n1+1) * dispPoly; 
trace = [];

first = 1;
while 1

    if lr %exists while rotating about a corner of the stationary
        rotA = 2*pi/n1;
    else
        rotA = 2*pi/n2;
    end
    rotPt = polyPt(l, s1, n1, r1);
    lb = l + lRem;
    side1 = floor(l / s1 - E);
    side1up = side1 + lr;
    p2cen = polyPt2(side1, lb/s1 -side1 - .5 * s2/s1, n1, r1) + d2 * cs(2*pi*(side1+.5)/n1);
    if first
        p2cen0 = p2cen;
        r = r + arg(p2cen0)/(2*pi);
    end

    for a = 0:astep:rotA    
        P2 = vert(r2, n2, 0:n2);
        P2 = rotm( pi +pi/n1 -pi/n2   +2*pi*side1/n1) * P2;
        P2 = arrpluspt(P2, p2cen);
        P2 = arrpluspt(P2, -rotPt);
        P2 = rotm(a) * P2;
        P2 = arrpluspt(P2, rotPt);
        trV = mod(floor(l/s2 + E) + lr, n2) + 1;

        cen = rotm(a) * (p2cen - rotPt) + rotPt;
        trace = [trace,P2(:,trV)]; 

        plot(P1(1,:), sgn*P1(2,:), P2(1,:)*dispPoly, sgn*P2(2,:)*dispPoly, trace(1,:),sgn*trace(2,:),P2(1,trV), sgn*P2(2,trV),'o');

        %plot(P1(1,:), P1(2,:), P2(1,:), P2(2,:), trace(1,:),trace(2,:),...
        %[0,p2cen0(1)],[0,p2cen0(2)],[0,cen(1)],[0,cen(2)], P2(1,trV), P2(2,trV),'o');

        axis([-plotmax,plotmax,-plotmax,plotmax]);
        axis square
        figure(1);
       if savegif
           drawnow
           frame = getframe(1); % plot window must be on same monitor!
           img = frame2im(frame);
           [img1,img2] = rgb2ind(img,256);
       end
       if first
           if savegif
               imwrite(img1,img2,'g','gif','DelayTime',2*delay); %control animation speed(but not really)
           end
           first = 0;
       else
           if savegif
               imwrite(img1,img2,'g','gif','WriteMode','append','DelayTime', 2*delay);
           end
       end
       pause(.01);

        adf = mod(arg(cen) - r*2*pi, 2*pi);
        if adf < astep & l/(n1*s1) + .5 > r
            return
        end

    end

%cleanup for next iteration 
    jump = lRem + ~lr * s2; 
    lnex = l + jump; 

    if floor(lnex / s1 - E) > side1up 
        lnex = s1*(side1up+1);
        lRem = jump - (lnex - l);
        lr = 1;
    else    
        lRem = 0;
        lr = 0;
    end
    l = lnex;
end

รหัส Golfed

function[]=f(r,h,H,n,N,d)
P=pi;T=2*P;F=@floor;C=@(a)[cos(a);sin(a)];g=@(i,f,n,r)r*C(T*i/n)*(1-f)+f*r*C(T*(i+1)/n);R=@(a)[C(a),C(a+P/2)];W=@(a,p)[a(1,:)+p(1);a(2,:)+p(2)];b=@(p)atan2(p(2),p(1));E=1e-9;d=d/d;S=1-2*(r>0);r=-r*S;x=2*h*sin(P/n);X=2*H*sin(P/N);M=h+2*H;l=0;z=0;L=0;A=h*C(T*(0:n)/n)*d;t=[];while 1
v=l/x;D=F(v-E);q=g(D,v-D,n,h);Z=D+L;c=g(D,v+z/x-D-.5*X/x,n,h)+H*cos(P/N)*C(T*D/n+P/n);r=r+~(l+L)*b(c)/T;for a=0:.1:T/(L*n+~L*N)
O=@(p)W(R(a)*W(p,-q),q);B=O(W(R(P+P/n-P/N+T*D/n)*H*C(T*(0:N)/N),c));t=[t,B(:,mod(F(l/X+E)+L,N)+1)];plot(A(1,:),S*A(2,:),d*B(1,:),d*S*B(2,:),t(1,:),t(2,:)*S)
axis([-M,M,-M,M],'square');pause(.1);if.1>mod(b(O(c))-r*T,T)&v/n+.5>r
return;end;end;j=z+~L*X;J=l+j;L=F(J/x-E)>Z;l=L*x*(Z+1)+~L*J;z=L*(J-l);end

คำแนะนำ:

ฟังก์ชั่นบันทึกไปยังไฟล์ที่มีชื่อเดียวกันคือหรือepic.m f.mเรียกใช้โดยเรียกใช้ฟังก์ชันจากคอนโซล Matlab

การใช้งาน: epic(r, r1, r2, n1, n2, dispPoly) โดยที่dispPolyเป็นตัวแปรบูลีน (ศูนย์ถ้าเป็นเท็จหมายเลขที่ไม่ใช่ศูนย์ถ้าเป็นจริง) กำหนดว่าจะวาดรูปหลายเหลี่ยม

แก้ไข: เพิ่มโบนัส 50 สำหรับภาพเคลื่อนไหว


14

Java - 2,726 2,634 - 200 = 2434 ตัวอักษร

ปรับปรุงจาก 3800 ish ไบต์

ขอบคุณสำหรับคำแนะนำของคุณ (โดยเฉพาะนามแฝง 118) นี่คือเวอร์ชันใหม่

ฉันเพิ่มคลาส P ซึ่งเป็นคลาสพอยต์และคลาส L ซึ่งขยาย ArrayList

ฉันยังเพิ่มการเปลี่ยนแปลงตรรกะเล็กน้อย

นี่คือคลาสหลัก (ไม่เล่นกอล์ฟ):

import java.awt.*;
import java.awt.geom.*;

import javax.swing.*;
public class Polygons2 extends JPanel{
    public static void main(String[] args) throws InterruptedException{new Polygons2(args);}
    double q=Math.PI*2;
    int d=1;
    public Polygons2(String[] args) throws InterruptedException{
        double revolutions=Double.valueOf(args[0])*q;
        double stationaryRadius = Double.valueOf(args[1]);
        double rollingRadius = Double.valueOf(args[2]);
        int stationarySides = Integer.valueOf(args[3]);
        int rollingSides = Integer.valueOf(args[4]);    
        double dist = stationaryRadius+rollingRadius+70;
        P sp = new P(dist,dist);
        P rp = new P(sp.x,sp.y-rollingRadius-stationaryRadius);
        //get points for rolling polygon and stationary polygon
        int key=0;
        for(double stationaryAngle=-q/4;stationaryAngle<q-q/4;stationaryAngle+=q/stationarySides){
            P p=new P(Math.cos(stationaryAngle)*stationaryRadius+sp.x,Math.sin(stationaryAngle)*stationaryRadius+sp.y);
            p.k=key;key++;
            stationaryPoints.add(p);
        }
        for(double rollingAngle=q/4;rollingAngle<q+q/4;rollingAngle+=q/rollingSides){
            P p=new P(Math.cos(rollingAngle)*rollingRadius+rp.x,Math.sin(rollingAngle)*rollingRadius + rp.y);
            p.k=key;key++;
            rollingPoints.add(p);
        }
        double g=(q/2)-((q/2-(q/rollingSides))/2) - ((q/2-(q/stationarySides))/2)-.05;
        for(P p:rollingPoints){p.r(getPoint(0), g);}
        //set up JFrame
        JFrame f = new JFrame();
        f.add(this);
        f.setSize((int)dist*2+60,(int)dist*2+60);
        f.setVisible(true);
        int[] pKeys= new int[]{stationaryPoints.get(0).k,rollingPoints.get(0).k};
        int index=1;
        P rc = rollingPoints.c();
        P sc =stationaryPoints.c();
        double currentRadian=Math.atan2(rc.y-sc.y,rc.x-sc.x);
        double totalRadian = 0;
        while(Math.abs(totalRadian)<revolutions){
            P rc2 = rollingPoints.c();
            P sc2 =stationaryPoints.c();
            double angle = Math.atan2(rc2.y-sc2.y,rc2.x-sc2.x);
            if(currentRadian-angle<2){totalRadian+=(angle-currentRadian);}
            currentRadian=angle;
            L clone=(L)path.clone();
            clone.add(new P(rollingPoints.get(1).x,rollingPoints.get(1).y));
            path = clone;
            for(P p:rollingPoints){
                p.r(getPoint(pKeys[index]),.01);
                int size = stationaryPoints.size();
                for(int i=0;i<size;i++){
                    P stationaryPointAtI = stationaryPoints.get(i);
                    P nextPoint=null;
                    if(i==size-1){nextPoint=stationaryPoints.get(0);}
                    else{nextPoint=stationaryPoints.get(i+1);}
                    if(p.b(stationaryPointAtI, nextPoint)==1&&containsKey(pKeys,p.k)==0){
                        //rolling point is between 2 stationary points
                        if(index==1){index=0;}else{index=1;}
                        pKeys[index]=p.k;
                    }
                    int size2=rollingPoints.size();
                    for(int h=0;h<size2;h++){
                        P nextPoint2=null;
                        if(h==size2-1){nextPoint2=rollingPoints.get(0);}
                        else{nextPoint2=rollingPoints.get(h+1);}
                        if(stationaryPointAtI.b(rollingPoints.get(h), nextPoint2)==1&&containsKey(pKeys,stationaryPointAtI.k)==0){
                            //stationary point is between 2 rolling points
                            if(index==1){index=0;}else{index=1;}
                            pKeys[index]=stationaryPointAtI.k;
                        }
                    }
                }
            }
            repaint();
            Thread.sleep(5);
        }
    }
    volatile L path = new L();
    L rollingPoints = new L();
    L stationaryPoints = new L();
    P getPoint(int key){
        for(P p:rollingPoints){if(p.k==key){return p;}}
        for(P p:stationaryPoints){if(p.k==key){return p;}}
        return null;
    }
    int containsKey(int[] keys,int key){
        for(int i:keys){if(key==i){return 1;}}
        return 0;
    }
    @Override
    public void paintComponent(Graphics g){
        Path2D.Double sPath = new Path2D.Double();
        sPath.moveTo(stationaryPoints.get(0).x, stationaryPoints.get(0).y);
        for(P p:stationaryPoints){
            sPath.lineTo(p.x, p.y);
        }
        sPath.closePath();
        Path2D.Double rPath = new Path2D.Double();
        rPath.moveTo(rollingPoints.get(0).x, rollingPoints.get(0).y);
        for(P p:rollingPoints){
            rPath.lineTo(p.x, p.y);
        }
        rPath.closePath();
        g.setColor(Color.white);
        g.fillRect(0,0,getWidth(),getHeight());
        Graphics2D t = (Graphics2D)g;
        if(d==1){
        t.setColor(Color.black);
        t.draw(sPath);
        t.setColor(Color.blue);
        t.draw(rPath);
        }
        g.setColor(Color.green);
        for(P p:path){g.fillOval((int)p.x-1, (int)p.y-1, 2, 2);}
    }
}

และรุ่น golfed:

import java.awt.*;import java.awt.geom.*;import javax.swing.*;import static java.lang.Math.*;class Polygons2Golfed extends JPanel{public static void main(String[]a)throws Exception{new Polygons2Golfed(a);}double q=PI*2;int d=1;public Polygons2Golfed(String[]a)throws Exception{double b,c,f;b=Double.valueOf(a[1]);c=Double.valueOf(a[2]);int d,e;d=Integer.valueOf(a[3]);e=Integer.valueOf(a[4]);f=b+c+100;P o=new P(f,f);P r=new P(o.x,o.y-c-b);int s=0;for(double u=-q/4;u<q-q/4;u+=q/d){P p=new P(cos(u)*b+o.x,sin(u)*b+o.y);p.k=s;s++;l.add(p);}for(double u=q/4;u<q+q/4;u+=q/e){P p=new P(cos(u)*c+r.x,sin(u)*c+r.y);p.k=s;s++;k.add(p);}double g=q/e/2+q/d/2-.05;for(P p:k){p.r(v(0),g);}JFrame j=new JFrame();j.add(this);j.setSize((int)f*2+60,(int)f*2+60);j.setVisible(true);m=new int[]{l.get(0).k,k.get(0).k};int ad=1;P rc=k.c();P sc=l.c();double ab,ac;ab=atan2(rc.y-sc.y,rc.x-sc.x);ac=0;while(abs(ac)<Double.valueOf(a[0])*q){P rc2=k.c();P sc2=l.c();double ah=atan2(rc2.y-sc2.y,rc2.x-sc2.x);if(ab-ah<2)ac+=(ah-ab);ab=ah;L ag=(L)n.clone();ag.add(new P(k.get(1).x,k.get(1).y));n=ag;for(P p:k){p.r(v(m[ad]),.01);int af=l.size();for(int i=0;i<af;i++){P aa=l.get(i);P w=null;if(i==af-1){w=l.get(0);}else{w=l.get(i+1);}if(p.b(aa, w)==1&&w(p.k)==0){if(ad==1)ad=0;else ad=1;m[ad]=p.k;}int ae=k.size();for(int h=0;h<ae;h++){P u=null;if(h==ae-1)u=k.get(0);else u=k.get(h+1);if(aa.b(k.get(h),u)==1&&w(aa.k)==0){if(ad==1)ad=0;else ad=1;m[ad]=aa.k;}}}}repaint();Thread.sleep(5);}}L n=new L();L k=new L();L l=new L();P v(int key){for(P p:k){if(p.k==key)return p;}for(P p:l){if(p.k==key)return p;}return null;}int[]m;int w(int key){for(int i:m){if(key==i)return 1;}return 0;}@Override public void paintComponent(Graphics g){Path2D.Double aq=new Path2D.Double();aq.moveTo(l.get(0).x,l.get(0).y);for(P p:l){aq.lineTo(p.x, p.y);}aq.closePath();Path2D.Double aw=new Path2D.Double();aw.moveTo(k.get(0).x, k.get(0).y);for(P p:k){aw.lineTo(p.x, p.y);}aw.closePath();g.setColor(Color.white);g.fillRect(0,0,getWidth(),getHeight());Graphics2D t=(Graphics2D)g;if(d==1){t.setColor(Color.black);t.draw(aq);t.setColor(Color.blue);t.draw(aw);}g.setColor(Color.green);for(P p:n){g.fillOval((int)p.x-1,(int)p.y-1,2,2);}}}

เช่นเดียวกับคลาส P:

import java.awt.geom.*;class P{double x,y;public P(double a,double b){x=a;y=b;}int k;void r(P c,double g){double a,r;a=Math.atan2(y-c.y,x-c.x)+g;r=Math.sqrt((c.x-x)*(c.x-x)+(c.y-y)*(c.y-y));x=Math.cos(a)*r+c.x;y=Math.sin(a)*r+c.y;}public int b(P a,P b){if(Line2D.ptSegDist(a.x,a.y,b.x,b.y,x,y)<.5)return 1;return 0;}}

และ L:

import java.util.*;public class L extends ArrayList<P>{public P c(){double x,y;x=0;y=0;for(P p:this){x+=p.x;y+=p.y;}return new P(x/size(),y/size());}}

เปลี่ยน int d เป็น 0 หรือ 1 เพื่อแสดงรูปหลายเหลี่ยม

ข้อโต้แย้ง - 1 100 50 5 2

ป้อนคำอธิบายรูปภาพที่นี่

args - 1.5 100 100 7 3

ป้อนคำอธิบายรูปภาพที่นี่

args - 2 40 100 3 7

ป้อนคำอธิบายรูปภาพที่นี่


เป็นr50 ในตัวอย่างทั้งหมดของคุณหรือไม่ นั่นหมายความว่าลูกกลิ้งจะมีค่าประมาณ 50 ครั้ง
งานอดิเรกของ Calvin

ตัวอย่างใหม่จาก @ Calvin's งานอดิเรกแสดง pi * 3
Stretch Maniac

1
@StretchManiac ไม่ถูกต้อง 3πควรนำคุณไปประมาณ 9 ครั้งรอบ ๆ รูปหลายเหลี่ยมที่อยู่กับที่
Martin Ender

4
มันตลกดีที่ชื่อคลาสอยู่RotatingPolygonsGolfedในรหัส "golfed" ในขณะที่อยู่RotatingPolygonsในรหัสปกติ ;)
งานอดิเรกของ Calvin

1
คุณสามารถบันทึกจำนวนอักขระที่ดีเพียงแค่เปลี่ยนการนำเข้าของคุณเพื่อใช้ * แทนคลาสที่เฉพาะเจาะจง ...
pseudonym117

12

Javascript, 1284 chars (-200 = 1084 chars)

รหัสย่อคือ

function epi(B,r2,r1,n2,n1){K=Math;function C(t){return K.cos(t)}function S(t){return K.sin(t)}function A(y,x){return K.atan2(y,x)}P=K.PI;v=[[],[]];w=[[],[]];z=[];function Z(x,y,j){c=C(t=f*H+P/2);s=S(t);v[j][n]=c*x-s*y;w[j][n]=s*x+c*y;}function E(i){return{x:r1*S(t=p-i*q),y:r1*C(t)};}function D(x,y,X,Y,t){L=A(m.y,m.x);M=K.sqrt(m.x*m.x+m.y*m.y);N=K.sqrt(X*X+Y*Y);O=~~(t*(M>N?M:N)+1);for(i=J;i<=O;i++){J=1;z[n]=f*H+P+t*i/O;Z(x+M*C(T=L+t*i/O),y+M*S(T),0);Z(x+N*C(T=A(Y,X)+t*i/O),y+N*S(T),1);n++}}function F(x,y,n,r,L,s){I.strokeStyle=s;I.beginPath();for(i=0;i<n;i++)I[i?'lineTo':'moveTo'](x+r*C(t=L+(1-2*i)*P/n),y+r*S(t)*W);I.closePath();I.stroke()}p=P/n1;q=2*p;u=P/n2;H=2*u;s2=r2*S(u);g=f=l=n=J=h=0;R=300;while(l<=(B*2+1)*P/H){o=E(0);m=E(h);m.y-=o.y;m.x-=o.x;if(g<s2){D(g,-r2*C(u),-o.x,-o.y,q);h=(h+1)%n1;g+=2*r1*S(p)}else{m.x+=g-s2;D(s2,-r2*C(u),-o.x+g-s2,-o.y,H);g-=s2*2;f=(f+1)%n2;l++}}return function(e_,t,aa,W_){W=aa?-1:1;I=(e=e_).getContext('2d');I.fillStyle='black';I.fillRect(0,0,600,600);W_&1&&F(R,R,n2,r2,0,'white');T=A(w[1][0],v[1][0]);U=V=0;I.strokeStyle='teal';I.beginPath();I.moveTo(R+v[0][0],R+w[0][0]*W);while(U<t){_=A(w[1][V+1],v[1][V+1]);U+=_-T+(_+1<T?2*P:0);T=_;V++;I.lineTo(R+v[0][V],R+w[0][V]*W)}W_&2&&I.stroke();W_&4&&F(R+v[1][V],R+w[1][V]*W,n1,r1,z[V],'red')}}

รหัสเต็มคือ

function epi( nr, r2, r1, n2, n1 ) {
function C( t )
    { return Math.cos( t ); }
function S( t )
    { return Math.sin( t ); }
function A( dy, dx )
    { return Math.atan2( dy, dx ); }

var iCCW, e, t_, xs = [[],[]], ys = [[],[]], ts = [], n = 0, iArc0 = 0;

function addpt( x, y, iBin ) {
    var c_ = C(t_ = iFrame*t2 + Math.PI/2 ),
        s_ = S(t_);

    xs[iBin][n] = c_*x-s_*y;
    ys[iBin][n] = s_*x+c_*y;
}

function poly1pt( iP )
    { return { x: r1*S(t_ = t1b2-iP*t1), y: r1*C(t_) }; }

function arc1( P_Arc_, xP_, yP_, xC_, yC_, t ) {
    var dx_, dy_, dxC, dyC;
    var t0 = A( dy_ = P_Arc_.y, dx_ = P_Arc_.x ),
        r_ = Math.sqrt( dx_*dx_ + dy_*dy_ ),
        t0C = A( dyC = yC_, dxC = xC_ ),
        rC = Math.sqrt( dxC*dxC + dyC*dyC ),
        nt = ~~(t*(r_>rC?r_:rC)+1);

    for( var i = iArc0; i <= nt; i++ ) {
        iArc0 = 1;
        ts[n] = iFrame*t2 + Math.PI + t*i/nt;
        addpt( xP_ + r_*C(t_ = t0+t*i/nt), yP_ + r_*S(t_), 0 );
        addpt( xP_ + rC*C(t_ = t0C+t*i/nt), yP_ + rC*S(t_), 1 );
        n++;
    }
}

function poly( x,y, n, r, t0, sColor ) {
    var Cx = e.getContext('2d');
    Cx.strokeStyle = sColor;
    Cx.beginPath();
    for( var i = 0; i < n; i++ )
        Cx[i ? 'lineTo' : 'moveTo']( x + r*C(t_ = t0+(1-2*i)*Math.PI/n), y + r*S(t_)*iCCW );

    Cx.closePath();
    Cx.stroke();
}

var t1b2 = Math.PI/n1,
    t1 = 2*t1b2,
    t2b2 = Math.PI/n2,
    t2 = 2*t2b2,
    s1 = 2*r1*S(t1b2),
    s2 = 2*r2*S(t2b2),
    xPivot = 0,
    iPivot = 0,
    iFrame = 0,
    P_Pivot, P_Arc,
    nFrame = 0;

while( nFrame <= (nr*2+1)*Math.PI/t2 ) {
    P_Pivot = poly1pt( 0 );
    P_Arc = poly1pt( iPivot );
    if( xPivot < s2/2 ) {
        P_Arc.x -= P_Pivot.x;
        P_Arc.y -= P_Pivot.y;
        arc1( P_Arc, xPivot, -r2*C(t2b2), -P_Pivot.x, -P_Pivot.y, t1 );
        iPivot = (iPivot+1) %n1;
        xPivot += s1;
    } else {
        P_Arc.x -= (P_Pivot.x - (xPivot - s2/2));
        P_Arc.y -= P_Pivot.y;
        arc1( P_Arc, s2/2, -r2*C(t2b2), -P_Pivot.x + xPivot - s2/2, -P_Pivot.y, t2 );
        xPivot -= s2;
        iFrame = (iFrame+1) %n2;
        nFrame++;
    }
}

function renderTo( eCanvas, t, isCCW, sWhat ) {
    iCCW = isCCW ? -1 : 1;
    var Cx = (e = eCanvas).getContext('2d');
    Cx.fillStyle = 'black';
    Cx.fillRect( 0,0, 600,600 );

    if( sWhat &1 )
        poly( 300,300, n2, r2, 0, 'white' );

    var tRef = A( ys[1][0], xs[1][0] ),
        tCum = 0,
        i0 = 0;

    Cx.strokeStyle = 'green';
    Cx.beginPath();
    Cx.moveTo( 300+xs[0][0], 300+ys[0][0]*iCCW );
    while( tCum < t ) {
        t_ = A( ys[1][i0+1], xs[1][i0+1] );
        tCum += t_ - tRef + (t_ - tRef < -1 ? 2*Math.PI : 0);
        tRef = t_;
        i0++;
        Cx.lineTo( 300+xs[0][i0], 300+ys[0][i0]*iCCW );
    }
    if( sWhat &2 )
        Cx.stroke();
    if( sWhat &4 )
        poly( 300+xs[1][i0], 300+ys[1][i0]*iCCW, n1, r1, ts[i0], 'red' );
}

return renderTo;
}

ซอที่เห็นเป็นกิจวัตรประจำวันในรัศมีภาพซ้อนหลายอันของมัน (และเพื่อแสดงให้เห็นภาพเคลื่อนไหว) มีอยู่ที่

http://jsfiddle.net/7rv751jy/2/embedded/result/

สคริปต์กำหนดฟังก์ชั่นที่เรียกepiว่ายอมรับพารามิเตอร์ที่ระบุไว้ห้ารายการใน OP epiส่งคืนฟังก์ชันที่มีลายเซ็น(e,t,isCCW,flags)ซึ่งยอมรับอาร์กิวเมนต์:

  • e - การอ้างอิงถึงองค์ประกอบผ้าใบ canvas5 600x600 HTML5 ที่จะแสดงผล
  • t- มุมรวม (เป็นเรเดียน) ที่เซนทรอยด์ของรูปหลายเหลี่ยมที่สองควรกวาดรอบเซนทรอยด์ของรูปแรก อาร์กิวเมนต์ผ่านไม่ควรเกิน 2 epiปี่เท่าของจำนวนการหมุนผ่านไป
  • isCCW - บูลีนระบุว่าการติดตามควรดำเนินการในทิศทางทวนเข็มนาฬิกา (ตรงข้ามกับทวนเข็มนาฬิกา)
  • flags - ชุดของค่าสถานะบิตระบุองค์ประกอบที่ควรเรนเดอร์
    • บิต 1 - สร้างรูปหลายเหลี่ยม 1 ถ้าตั้งค่าไว้
    • บิต 2 - เรนเดอร์การติดตามถ้าตั้งค่าไว้
    • บิต 3 - แสดงรูปหลายเหลี่ยม 2 หากตั้งค่าไว้

ฟังก์ชั่นสามารถเรียกได้ว่าจำนวนครั้งใด ๆ กับชุดของการขัดแย้งที่แตกต่างกัน

หมายเหตุบางส่วน:

  • ขั้นตอนการจัดการกรณีที่เลวที่และn1 = 2 / หรือ n2 = 2เมื่อเคลื่อนไหวการรวมความยาวบางอย่างจะทำให้เกิดความก้าวหน้าอย่างรวดเร็วอย่างรวดเร็วในการติดตาม นี่เป็นเพราะเฟรมภาพเคลื่อนไหวถูกทำดัชนีโดยมุมไปยัง centroid ของรูปหลายเหลี่ยมที่สองและ d theta poly2 / d theta centroid กลายเป็นเอกพจน์ในกรณีที่ centroid ของ 2-poly 2 อยู่ใกล้จุดสุดยอดของ 2-poly 1 อย่างไรก็ตามสิ่งนี้ไม่มีผลต่อการติดตาม

  • ชื่อพารามิเตอร์ในepiจะดูสับสนตั้งแต่การพัฒนาฉันเรียกรูปหลายเหลี่ยม 1 ว่า "2" และรูปหลายเหลี่ยม 2 เป็น "1" เมื่อฉันตระหนักความไม่สอดคล้องกันระหว่างการประชุมของฉันและของ OP epiที่มากกว่าการแลกเปลี่ยนทั้งหมดของดัชนีในรหัสผมก็เปลี่ยนคำสั่งของการขัดแย้งใน

  • ซอด้านบนนำเข้า jQuery แต่นี่คือการจัดการ UI epiฟังก์ชั่นไม่เคยมีใครอ้างอิงห้องสมุด

  • รหัสจะจัดการกับร่องรอย CCW เพียงแค่หมุนแกน Y นี่ค่อนข้างไม่เหมาะสมเนื่องจากรูปหลายเหลี่ยม 2 เริ่มต้นในตำแหน่ง Y-inverted ในระหว่างการติดตาม CCW แต่ไม่มีใครบอกว่ากิจวัตรต้องสง่างาม ;)


1
สวย! ฉันพบว่าลิงก์แบบเต็มหน้าจอนั้นใช้งานได้ง่ายที่สุด: jsfiddle.net/7rv751jy/embedded/result
งานอดิเรกของ Calvin

หนึ่งร้องเรียนเล็ก ๆ คือจุดสุดยอดติดตามไม่ได้เริ่มต้นที่จุดสุดยอดนิ่ง
งานอดิเรกของ Calvin

ฮ้า ฉันมองข้ามอย่างสิ้นเชิงว่าในสเป็ค ฉันพูดว่า 'ฮา' เพราะรหัสเดิม (โดยไม่ตั้งใจ) เป็นสเป็ค แต่ฉันเปลี่ยนจุดสุดยอดการติดตามเพราะฉันคิดว่าการติดตามจะดูดีขึ้นถ้ามันเริ่มทันที ฉันได้อัปเดตโค้ดเพื่อให้เป็นสเป็คและอัปเดตลิงก์ไปยังซอไปเป็นเวอร์ชันเต็มตามข้อกำหนดสเป็คเต็มจอ เป็นโบนัสมันทำให้ตัวละครตัวหนึ่งหลุดออกจากการนับทั้งหมด
COTO

ฉันจะเร่งความเร็วได้อย่างไร JS noob ที่นี่
Soham Chowdhury

@ShaamChowdhury: เปลี่ยนรหัสnt = ~~(t*(r_>rC?r_:rC)+1)เป็นnt = ~~(t*(r_>rC?r_:rC)/10+1)และควรเร่งความเร็วให้เร็วขึ้น
COTO
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.