当前位置:网站首页>Romance of programmers on Valentine's Day

Romance of programmers on Valentine's Day

2022-07-05 05:15:00 ximen502_

   Searched the romantic love story between Descartes and Swedish Princess , It mentions a cardioid function , But it looks like a function of polar coordinates . The following is achieved with the help of the big guy's mathematical formula and other big guy's code , transplant java Swing and android Platform . soon 2.14 The no. , I wish lovers a happy ending , a wife lifts the tray to a level with her eyebrows to show great respect for her husband , Respect , live to old age in conjugal bliss .
https://mathworld.wolfram.com/HeartCurve.html

1. Drawing of cardioid curve

x = 16   sin ⁡ 3 t x=16\,\sin^{3}t x=16sin3t
y = 13   cos ⁡ t − 5 cos ⁡ ( 2 t ) − 2 cos ⁡ ( 3 t ) − cos ⁡ ( 4 t ) y=13\,\cos t - 5\cos(2t)-2\cos(3t)-\cos(4t) y=13cost5cos(2t)2cos(3t)cos(4t)

The renderings are as follows :
 Insert picture description here    unfortunately swing Of graphics Drawing method parameters only support int type , The curve is not smooth , Can be in android Draw a smoother curve inside ,android The line drawing method of supports floating point numbers . The drawing of this curve refers to the blog code of many bosses , stay android and swing All of them have been transformed successfully . The latter coordinate axis can be removed , Plus just for reference .

2. Cardioid curve animation

2.1 effect 1

If it's just a static diagram, it's also a little boring , Try to make the curve drawing process visible , Add a delay .
 Insert picture description here

2.2 effect 2

Draw down from the middle of the top at the same time
 Insert picture description here

2.3 effect 3 Change drawing lines to drawing pictures

 Insert picture description here

import java.awt.*
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JPanel
//  Animated version of the painting heart , Draw clockwise from the top 
class HeartFrameKt2 : JFrame() {
    
    init {
    
        val panel = HeartPanel()
        val jButton = JButton("refresh")
        add(panel, BorderLayout.CENTER)
        add(jButton, BorderLayout.SOUTH)
        var thread = Thread {
    
            while (true) {
    
                var refresh = true
                EventQueue.invokeLater {
    
                    refresh = panel.refresh()
                }
                Thread.sleep(25)
            }
        }
        thread.start()
        jButton.addActionListener {
    
            panel.clear()
        }
    }

    inner class HeartPanel : JPanel() {
    
        var i = 0.0
        var list = mutableListOf<OkPoint>()
        override fun paintComponent(g: Graphics?) {
    
            super.paintComponent(g)
            var g2: Graphics2D = g as Graphics2D
            g2.translate(width / 2, height / 2)
            drawAxis(g)
            // Trim the line thickness 
            g2.stroke = BasicStroke(3.0f)
            g2.color = Color.RED

            val inc = Math.PI / 90
            if (i <= 2 * Math.PI) {
    
                var x = getX(20, i.toFloat())
                var y = getY(20, i.toFloat())
                var p = OkPoint(x, y)
                list.add(p)
                i += inc
            }

            for (i in list.indices) {
    
                if (i < list.size - 1) {
    
                    var p0 = list.get(i)
                    var p1 = list.get(i + 1)
                    g2.drawLine(p0.x.toInt(), p0.y.toInt(), p1.x.toInt(), p1.y.toInt())
                }
            }

            g2.translate(-width / 2, -height / 2)
        }

        fun getX(zoom: Int, theta: Float): Double {
    
            return zoom * (16 * Math.pow(Math.sin(theta.toDouble()), 3.0))
        }

        fun getY(zoom: Int, theta: Float): Double {
    
            return (-zoom
                    * (13 * Math.cos(theta.toDouble()) - 5 * Math.cos((2 * theta).toDouble()) - (2
                    * Math.cos((3 * theta).toDouble())) - Math.cos((4 * theta).toDouble())))
        }

        fun drawAxis(g: Graphics?) {
    
            var g2: Graphics2D = g as Graphics2D
            g2.stroke = BasicStroke(1.0f)
            g2.color = Color.BLACK
            g2.drawLine(-width / 2, 0, width / 2, 0)
            g2.drawLine(0, -height / 2, 0, height / 2)
            //unit=10,vertical line,x1,y1,x2,y2
            // short line, long line
            val sl = 5
            val ll = 10
            //x axis
            for (i in 0..width / 2 step 10) {
    
                if (i % 50 == 0) {
    
                    g2.drawLine(i, 0, i, -ll)
                    g2.drawLine(-i, 0, -i, -ll)
                } else {
    
                    g2.drawLine(i, 0, i, -sl)
                    g2.drawLine(-i, 0, -i, -sl)
                }
            }
            //y axis
            for (i in 0..height / 2 step 10) {
    
                if (i % 50 == 0) {
    
                    g2.drawLine(0, i, ll, i)
                    g2.drawLine(0, -i, ll, -i)
                } else {
    
                    g2.drawLine(0, i, sl, i)
                    g2.drawLine(0, -i, sl, -i)
                }
            }
        }

        fun refresh():Boolean {
    
            return if (i <= 2 * Math.PI) {
    
                repaint()
                true
            } else {
    
                false
            }
        }

        fun clear() {
    
            i = 0.0
            list.clear()
        }
    }

    inner class OkPoint(var x: Double, var y: Double)
}

fun main(args: Array<String>) {
    
    var frame = HeartFrameKt2()
    frame.apply {
    
        setSize(1500, 800)
        title = "Kotlin heart"
        setLocationRelativeTo(null) // Center the frame

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        isVisible = true
    }
}

  Android edition

public class ValentineView extends View {
    

    Paint paint;
    int w, h;
    Bitmap flower;
    Canvas hearCanvas;
    Bitmap bmpHeart;
    float leftAngle = (float)( 2*Math.PI);
    float rightAngle = 0;
    double inc = Math.PI / 45;
    int zoom = 1;
    float finalTxSize;

    public ValentineView(Context context, AttributeSet attrs) {
    
        super(context, attrs);
        float density = getResources().getDisplayMetrics().density;
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#FFDB9C"));
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setTextSize(/*density*22*/0);
        paint.setStrokeWidth(2);
        paint.setDither(true);

        flower = BitmapFactory.decodeResource(getResources(), R.mipmap.heart);

        finalTxSize = density * 22;
    }

    public ValentineView(Context context) {
    
        this(context, null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int wM = MeasureSpec.getMode(widthMeasureSpec);
        int hM = MeasureSpec.getMode(heightMeasureSpec);
        if (wM == MeasureSpec.EXACTLY) {
    
            w = MeasureSpec.getSize(widthMeasureSpec);
        }

        if (hM == MeasureSpec.EXACTLY) {
    
            h = MeasureSpec.getSize(heightMeasureSpec);
        }

        setMeasuredDimension(w, h);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    
        super.onSizeChanged(w, h, oldw, oldh);
        hearCanvas = new Canvas();
        bmpHeart = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        hearCanvas.setBitmap(bmpHeart);
        //  Calculate the magnification required , Spread all over the screen width 
        zoom = (int) Math.ceil(w / 2.0 / 16.0 - 4);
    }


    @Override
    protected void onDraw(Canvas canvas) {
    
        super.onDraw(canvas);
        drawHeart(canvas);
        canvas.drawBitmap(bmpHeart, 0, 0, paint);

        if (rightAngle > Math.PI || leftAngle < Math.PI){
    
            Log.d("xxx", "draw hear ok");
            paint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(" Happy Valentine's Day ", w/2, h/2, paint);
            paint.setTextAlign(Paint.Align.LEFT);

            if (paint.getTextSize() <= finalTxSize) {
    
                paint.setTextSize(paint.getTextSize()+1);
                postInvalidateDelayed(25);
            }else{
    
                Log.d("xxx", "draw txt ok");
            }
        }
    }

    private void drawHeart(Canvas canvas) {
    
        hearCanvas.save();
        hearCanvas.translate(w / 2, h / 2);//
        
        float leftX = (float) getX(zoom, leftAngle);
        float leftY = (float) getY(zoom, leftAngle);
        float rightX = (float) getX(zoom, rightAngle);
        float rightY = (float) getY(zoom, rightAngle);
        //Log.d("xxx", String.format("x:%s, y:%s", x, y));
        hearCanvas.save();
        hearCanvas.translate(-flower.getWidth()/2, -flower.getHeight()/2);
        hearCanvas.drawBitmap(flower, leftX, leftY, paint);
        hearCanvas.drawBitmap(flower, rightX, rightY, paint);
        hearCanvas.restore();
        hearCanvas.restore();
        

        // right half
        if(rightAngle <= Math.PI){
    
            rightAngle += inc;
            //postInvalidateDelayed(50);
        }

        // left half
        if(leftAngle >= Math.PI){
    
            leftAngle -= inc;
            postInvalidateDelayed(50);
        }
    }

    double getX(int zoom, float theta) {
    
        return zoom * (16 * Math.pow(Math.sin(theta), 3));
    }

    double getY(int zoom, float theta) {
    
        return -zoom
                * (13 * Math.cos(theta) - 5 * Math.cos(2 * theta) - 2
                * Math.cos(3 * theta) - Math.cos(4 * theta));
    }

}

   More code , Please refer to github:https://github.com/ximen502/SwingLearn,Swing of use kotlin It's pretty good ,kotlin It's really simple and powerful , and java Form a good complementary .

  Swing Medium JPanel Yes 2 One function is as a sub panel container , The other is that it can be used to customize components (view), Rewrite the method to realize custom drawing .

Refer to the user qq_32250025 Heart curve formula blog , thank .

原网站

版权声明
本文为[ximen502_]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202140623325192.html