Coding/Python 삽질기2022. 4. 23. 00:49

C library 작성

#include <stdio.h>
int add(int left, int right) {
    return left+right;
}
 
C library 빌드
gcc -shared -o libaddnumber.so add_number.c
 

Python Code 작성

from ctypes import CDLL
 
def main():
    c_func = CDLL('./libaddnumber.so')
    print(c_func.add(10, 20))
 
if __name__ == '__main__':
    main()
 
 
실행결과
chobocho@Chobocho-Mint:~/github/python/sharedlib$ python3 add_number.py 
30

'Coding > Python 삽질기' 카테고리의 다른 글

About Pyscript  (0) 2022.06.10
[PyTorch] CUDA 설치기  (0) 2022.02.21
생일 문제  (0) 2021.06.21
Posted by chobocho
Coding/좋은 사이트2022. 4. 18. 23:38

'Coding > 좋은 사이트' 카테고리의 다른 글

하트 그리기  (0) 2018.03.07
함수의 그래프를 그려주는 사이트  (0) 2018.03.03
무료 에디터  (1) 2017.07.27
Posted by chobocho
My Life/version 6.12022. 4. 18. 00:19

프로그래밍 중급(?) 수준에 이르기 위해서 보면 좋을 책을 내 마음 대로 정리해 보았습니다.

재미로 읽어보시길 바랍니다.

좋은 책 있으시면 추천 부탁드립니다.

- 중급 -
Clean architecture
Clean code
Clean coder
Clean software
CODE
Code craft
Code complete 2
DNS 실전 교과서
Effective java 3/e
GoF의 디자인 패턴
Head First Design Pattern 2/e
Refactoring 2/e
System Design Interview Volume 2
가상 면접 사례로 배우는 대규모 시스템 설계 기초
개발자의 글쓰기
구글의 아침은 자유가 시작된다
구글 엔지니어는 이렇게 일한다
김도형의 데이터 사이언스 스쿨 수학 편
모던 자바 인 액션
맨먼스 미신
밑바닥부터 만드는 컴퓨팅 시스템
밑바닥부터 시작하는 딥러닝 3/e
생각하는 프로그래밍
소프트웨어 장인
실용주의 프로그래밍
이펙티브 코틀린
조엘 온 소프트웨어
컴파일러 구조와 원리 - 컴파일러로 배우는 언어 처리 시스템
테스트 주도 개발
프로그래머의 길, 멘토에게 묻다
피플웨어
한 권으로 읽는 컴퓨터 구조와 프로그래밍
해커와 화가
핸즈온 머신러닝
해커의 기쁨 2/e

- 초급 -
1일 1로그 100일 완성 IT 지식
그림으로 공부하는 TCP/IP 구조
파이썬 알고리즘 인터뷰

Posted by chobocho
My Life/version 19 (2019)2022. 3. 25. 21:20
.
오랜만에 책장속에 숨어있던, '어린왕자'를 꺼내 읽었다.
.
책을 다 읽고 관련 내용을 검색을 하다가 '어린왕자 명대사 명언 XX선'이란 글들을 보았다.
그런데 그 중에 '어린왕자'에서 못 본 문구들이 보였다.
.
나의 기억력에 문제가 있는게 아닐까 하는 불안감 속에, 기억
력 자가 검증을 위하여 전자책의 검색 기능을 활용하여 체크를 했는데,
다행히 내 기억이 옳았다.
내가 못봤다고 생각한 문구들은 책에 없었다.
.
많은 블로그와 브런치 글들에서 비슷한 오류가 보였다.
다들 책을 안 읽고 어디 비슷한 소스에서 Copy & Paste로 검증 없이 붙인것 같았다.
.
인터넷에서 찾은 자료는 잘못된 정보가 포함되었을 가능성이 높다는 걸 오늘도 배웠다.
.
결론: 인터넷 자료는 항상 검증이 필요하다.

'My Life > version 19 (2019)' 카테고리의 다른 글

자바스크립트로 네모네로 로직 만들기  (0) 2019.05.03
나의 다이어트 후기 (feat 85kg → 65kg)  (0) 2019.04.08
StarUML 구매  (0) 2019.01.31
Posted by chobocho
My Life/Mobile2022. 3. 1. 23:16

sharedate:*

로 검색 창에서 검색하면 된다.

Posted by chobocho
Coding/Python 삽질기2022. 2. 21. 23:37

PyTorch에서 GPU를 사용해보기로 하고, 삽질한 기록을

미래의 나를 위하여, 기록하였습니다.

1. 노트북 그래픽 카드 확인

 

2. Pytorch 사이트에서 CUDA 버전을 확인한다.

https://pytorch.org/get-started/locally/

 

PyTorch

An open source machine learning framework that accelerates the path from research prototyping to production deployment.

pytorch.org

 PyTorch 1.10.2에 Pip로 CUDA 10.2를 선택하면, 아래에 pip3 명령어가 보인다.  이를 사용하여 pytorch를 설치한다.

 

3. CUDA library 설치

PyTorch 사이트에서 확인한 CUDA 10.2 버전을 설치한다.

 

* 간혹 NVIDIA experience가 동작을 안하는 경우에는 아래와 같이

NVIDIA LocalSystem Controller 에서 로컬 시스템 계정 항목을 체크해 준다.

4. 파이썬을 실행해서 확인 해 본다.

 

'Coding > Python 삽질기' 카테고리의 다른 글

[Python] C 함수 호출 하기  (0) 2022.04.23
생일 문제  (0) 2021.06.21
[Python/C] 휴대폰 패턴의 가지수  (0) 2021.02.21
Posted by chobocho

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Mandelbrot</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>

<script language="JavaScript">
    // Start: 2022.02.02
    // Update: 2022.02.02

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let imageData;

    let scaleX = 1.0;
    let scaleY = 1.0;
    let mx = 1.0;
    let my = 1.0;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");

        imageData = bufCtx.createImageData(canvas.width, canvas.height);
    }

    function _draw(x1, y1, x2, y2) {
        const MAX_COUNT = 256;

        // X = -3.0 ~ 3.0
        // Y = -2.0 ~ 2.0
        // Z = X + Yi

        mx = x1 < -3.0 ? -3.0 : x1;
        my = y1 < -2.0 ? -2.0 : y1;

        x2 = x2 > 3.0 ? 3.0 : x2;
        y2 = y2 > 2.0 ? 2.0 : y2;

        let mw = x2 - x1;
        let mh = y2 - y1;

        console.log(x1, y1, x2, y2, " : ", mx, my, " : ", mw, mh);

        scaleX = mw / imageData.width;
        scaleY = mh / imageData.height;

        for (let i = 0; i < imageData.height; i++) {
            for (let j = 0; j < imageData.width; j++) {

                let c = 0;
                let x = mx + j * scaleX;
                let y = my + i * scaleY;
                let sx = x;
                let sy = y;

                for (c = 0; c < MAX_COUNT; c++) {
                    if (x**2 + y**2 > 4) {
                        break;
                    }
                    let nx = x**2 - y**2;
                    let ny = 2 * x * y;
                    x = nx + sx;
                    y = ny + sy;
                }

                let pos = 4 * (i * imageData.width + j);
                let color = 3 * c / MAX_COUNT;

                if (color < 1) {
                    imageData.data[pos+0]  = 255 * color;
                    imageData.data[pos+1] = color;
                    imageData.data[pos+2] = color;
                }
                else if (color < 2 ) {
                    imageData.data[pos+0] = 255;
                    imageData.data[pos+1] = color;
                    imageData.data[pos+2] = 0;
                } else {
                    imageData.data[pos+0] = 255;
                    imageData.data[pos+1] = 255;
                    imageData.data[pos+2] = color;
                }

                imageData.data[pos+3] = 255;
            }
        }

        bufCtx.putImageData(imageData, 0, 0);
        console.log("_OnDraw2()");
    }

    function OnDraw() {
        _draw(-3.0, -2.0, 3.0, 2.0);
        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);
    }

    function rectMouseMove(event) {
        // console.log("rectMouseMove");
        var currentPos = getMousePosition(event);
        cvs.beginPath();

        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);

        cvs.strokeStyle = pos.color;
        var box = {
            W: currentPos.X - pos.sx,
            H: currentPos.Y - pos.sy
        };

        cvs.strokeRect(pos.sx, pos.sy, box.W, box.H);

        cvs.stroke();
        cvs.closePath();
    }

    function rectMouseUp(event) {
        if (pos.isDraw) {
            console.log("rectMouseUp");
            var currentPos = getMousePosition(event);

            pos.ex = currentPos.X;
            pos.ey = currentPos.Y;

            if (pos.sx > pos.ex) {
                let t = pos.sx;
                pos.sx = pos.ex;
                pos.ex = t;
            }

            if (pos.sy > pos.ey) {
                let t = pos.sy;
                pos.sy = pos.ey;
                pos.ey = t;
            }

            let sx = mx + pos.sx * scaleX;
            let sy = my + pos.sy * scaleY;
            let ex = mx + pos.ex * scaleX;
            let ey = my + pos.ey * scaleY ;

            _draw(sx, sy, ex, ey);
            cvs.clearRect(0, 0, canvas.width, canvas.height);
            cvs.drawImage(bufCanvas, 0, 0);

            pos.isDraw = false;
        }
    }

    function rectMouseDown(event) {
        console.log("rectMouseDown");
        if (pos.isDraw) {
            return;
        }
        bufCtx.putImageData(imageData, 0, 0);
        //bufCtx.drawImage(canvas, 0, 0);
        pos.isDraw = true;
        var startPos = getMousePosition(event);
        pos.sx = startPos.X;
        pos.sy = startPos.Y;
    }

    function mouseListener(event) {
        switch (event.type) {
            case "mousedown":
                if (!pos.isDraw) {
                    pos.mouseDownAction(event);
                }
                break;
            case "mousemove":
                if (pos.isDraw) {
                    pos.mouseMoveAction(event);
                }
                break;
            case "mouseup":
            case "mouseout":
                if (pos.isDraw) {
                    pos.mouseUpAction(event);
                }
                break;
        }
    }

    function InitMouseEvent() {
        canvas.addEventListener("mousedown", mouseListener);
        canvas.addEventListener("mousemove", mouseListener);
        canvas.addEventListener("mouseout", mouseListener);
        canvas.addEventListener("mouseup", mouseListener);
    }

    function getMousePosition(event) {
        var x = event.pageX - canvas.offsetLeft;
        var y = event.pageY - canvas.offsetTop;
        return { X: x, Y: y };
    }

    var pos = {
        isDraw: false,
        mouseDownAction: rectMouseDown,
        mouseUpAction: rectMouseUp,
        mouseMoveAction: rectMouseMove,
        color: "rgb(255,211,25,255)",
        sx: 0,
        sy: 0,
        ex: 0,
        ey: 0
    }

    function onLoadPage() {
        InitCanvas();
        InitMouseEvent();
        OnDraw();
    }

    window.onload = onLoadPage();
</script>
</body>
</html>
Posted by chobocho

자바스크립트로 만델브로트 집합을 구현해 보았다.

만델브로트 집합

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Mandelbrot</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>

<script language="JavaScript">
    // Start: 2022.02.02
    // Update: 2022.02.02

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function _draw() {
        let imageData = bufCtx.createImageData(canvas.width, canvas.height);
        const MAX_COUNT = 255;

        // X = -3.0 ~ 3.0
        // Y = -2.0 ~ 2.0
        // Z = X + Yi

        let mx = -3.0;
        let my = -2.0;
        let mw = 6.0;
        let mh = 4.0;
        let scaleX = mw / imageData.width;
        let scaleY = mh / imageData.height;

        for (let i = 0; i < imageData.height; i++) {
            for (let j = 0; j < imageData.width; j++) {

                let c = 0;
                let x = mx + j * scaleX;
                let y = my + i * scaleY;
                let sx = x;
                let sy = y;

                for (c = 0; c < MAX_COUNT; c++) {
                    if (x**2 + y**2 > 4) {
                        break;
                    }
                    let nx = x**2 - y**2;
                    let ny = 2 * x * y;
                    x = nx + sx;
                    y = ny + sy;
                }

                let pos = 4 * (i * imageData.width + j);

                imageData.data[pos+0] = c;
                imageData.data[pos+1] = c;
                imageData.data[pos+2] = c;
                imageData.data[pos+3] = 255;
            }
        }

        bufCtx.putImageData(imageData, 0, 0);
    }

    function OnDraw() {
        _draw();
        cvs.beginPath();
        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);
    }

    function onLoadPage() {
        InitCanvas();
        OnDraw();
    }

    window.onload = onLoadPage();
</script>
</body>
</html>
Posted by chobocho
Coding/JavsScript 삽질기2022. 1. 20. 00:12
Sphere

 


 

소스는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sphere</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    // Start: 2022.01.16
    // Update: 2022.01.18

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let thetaX = 0;
    let thetaZ = 0;

    let maxSize = 0;
    let dimen = 12;
    let ox = 0;
    let oy = 0;
    let R1 = 1;  // 원의 반지름
    let R2 = 1;  // 회전 중심과의 거리
    let R3 = 1;
    let ZZ2 = 5000;

    let SIN = [];
    let COS = [];

    function InitValue() {
        for (let i = 0; i < 628; i++) {
            SIN[i] = Math.sin(i / 100);
            COS[i] = Math.cos(i / 100);
        }
    }

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        console.log(">Width:", width);
        console.log(">Heigth:", height);

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");

        maxSize = canvas.height < canvas.width ? canvas.height : canvas.width;

        ox = canvas.width / 2;
        oy = canvas.height / 2;
        R1 = maxSize/20;  // 원의 반지름
        R2 = maxSize/10;  // 회전 중심과의 거리
        R3 = maxSize/10;
    }

    function drawCircle(x, y, c, r) {
        if (c <= 0 || c >= 255){
            console.log(c);
        }

        bufCtx.beginPath();
        bufCtx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
        bufCtx.strokeStyle = "rgb(255, 255, 255)";
        bufCtx.arc(x, y, r, 0, Math.PI * 2);
        bufCtx.stroke();
        bufCtx.fill();
        bufCtx.closePath();
    }

    function _draw() {
        if (maxSize == 0) {
            return;
        }
        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 1000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)

        let points = [];
        _drawDoughnut(points);
        _drawSphere(points);

        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fillRect(0, 0, canvas.width, canvas.height);
        points.forEach(e => drawCircle(e[0], e[1], e[2], 1));

        thetaX = (thetaX + 2) % 629;
        thetaZ = (thetaZ + 2) % 629;
    }


    function _drawDoughnut(points) {
        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 5000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)
        let ZZ1 = maxSize * ZZ2 * 0.4 / (R1 + R2);

        for (let i = 0; i < 628; i += dimen) {
            let x1 = COS[i] * R1 + R2;
            let y1 = SIN[i] * R1;
            let nx1 = COS[i];
            let ny1 = SIN[i];

            for (let j = 0; j < 628; j += dimen) {
                // Y축 회전
                let x2 = x1 * COS[j];
                let y2 = y1;
                let z2 = x1 * SIN[j];

                let nx2 = nx1 * COS[j];
                let ny2 = ny1;
                let nz2 = nx1 * SIN[j];

                // X축 회전
                let x3 = x2;
                let y3 = y2 * COS[thetaX] - z2 * SIN[thetaX];
                let z3 = y2 * SIN[thetaX] + z2 * COS[thetaX];

                let nx3 = nx2;
                let ny3 = ny2 * COS[thetaX] - nz2 * SIN[thetaX];
                let nz3 = ny2 * SIN[thetaX] + nz2 * COS[thetaX];

                // Z축 회전
                let x4 = x3 * COS[thetaZ] - y3 * SIN[thetaZ];
                let y4 = x3 * SIN[thetaZ] + y3 * COS[thetaZ];
                let z4 = ZZ2 * 2 + z3;

                let nx4 = nx3 * COS[thetaZ] - ny3 * SIN[thetaZ];
                let ny4 = nx3 * SIN[thetaZ] + ny3 * COS[thetaZ];
                let nz4 = nz3;

                // 법선 벡터 (nx4, ny4, nz)와 광원의 백터 내적 계산
                // 광원 위치는 (0, 0, -1)
                let lx = 0;
                let ly = 0;
                let lz = -1;
                let light = nx4 * lx + ny4 * ly + nz4 * lz;

                if (light > 0) {
                    let color = Math.round(light * 255);

                    // x' = xz'/z, y' = yz'/z
                    let xp = Math.floor(x4 * ZZ1 / z4);
                    let yp = Math.floor(-y4 * ZZ1 / z4);

                    points.push([xp + ox, yp + oy, 255-color]);
                }
            }
        }
    }


    function _drawSphere(points) {
        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 1000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)

        ZZ1 = maxSize * ZZ2 * 0.4 / (R1 + R2 + R3);

        for (let i = 0; i < 628; i += dimen) {
            let x1 = COS[i] * R1;
            let y1 = SIN[i] * R1;
            let nx1 = COS[i];
            let ny1 = SIN[i];

            for (let j = 0; j < 628; j += dimen) {
                // Y축 회전
                let x2 = x1 * COS[j];
                let y2 = y1;
                let z2 = x1 * SIN[j];

                let nx2 = nx1 * COS[j];
                let ny2 = ny1;
                let nz2 = nx1 * SIN[j];

                // Z축 회전
                let x3 = x2 * COS[thetaX] - y2 * SIN[thetaX];
                let y3 = x2 * SIN[thetaX] + y2 * COS[thetaX];
                let z3 = z2;

                let nx3 = nx2 * COS[thetaX] - ny2 * SIN[thetaX];
                let ny3 = nx2 * SIN[thetaX] + ny2 * COS[thetaX];
                let nz3 = nz2;

                // X축 회전
                let x4 = x3 + R2 + R3;
                let y4 = y3 * COS[thetaX] - z3 * SIN[thetaX];
                let z4 = y3 * SIN[thetaX] + z3 * COS[thetaX];

                let nx4 = nx3;
                let ny4 = ny3 * COS[thetaX] - nz3 * SIN[thetaX];
                let nz4 = ny3 * SIN[thetaX] + nz3 * COS[thetaX];

                // Z축 시계 방향 회전
                let x5 = x4 * COS[thetaZ] + y4 * SIN[thetaZ];
                let y5 = -x4 * SIN[thetaZ] + y4 * COS[thetaZ];
                let z5 = ZZ2 + z4;

                let nx5 = nx4 * COS[thetaZ] + ny4 * SIN[thetaZ];
                let ny5 = -nx4 * SIN[thetaZ] + ny4 * COS[thetaZ];
                let nz5 = nz4;

                // 법선 벡터 (nx4, ny4, nz)와 광원의 백터 내적 계산
                // 광원 위치는 (0, 0, -1)
                let lx = 0;
                let ly = 0;
                let lz = -1;
                let light = nx5 * lx + ny5 * ly + nz5 * lz;

                if (light > 0) {
                    let color = Math.round(light * 255);

                    // x' = xz'/z, y' = yz'/z
                    let xp = Math.floor(x5 * ZZ1 / z5);
                    let yp = Math.floor(-y5 * ZZ1 / z5);

                    points.push([xp + ox, yp + oy, 255-color]);
                }
            }
        }
    }

    function OnDraw() {
        _draw();

        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);
    }


    function onLoadPage() {
        InitValue();
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>
Posted by chobocho
Coding/JavsScript 삽질기2022. 1. 19. 10:25

유튜브에서본 회전 하는 3D 도넛을 구현해 보았다.

3D doughnut

코드는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D doughnut</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <style>
        canvas {
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
<div align='center'>
    <canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
    // Start: 2022.01.16
    // Update: 2022.01.18

    let cvs;
    let canvas;
    let bufCanvas;
    let bufCtx;
    let thetaX = 127;
    let thetaZ = 0;

    function InitCanvas() {
        height = window.innerHeight;
        width = window.innerWidth;

        canvas = document.getElementById("canvas");
        canvas.width = width;
        canvas.height = height;
        cvs = canvas.getContext("2d");

        bufCanvas = document.createElement("canvas");
        bufCanvas.width = canvas.width;
        bufCanvas.height = canvas.height;
        bufCtx = bufCanvas.getContext("2d");
    }

    function drawCircle(x, y, c, r) {
        if (c <= 0 || c >= 255){
            console.log(c);
        }

        bufCtx.beginPath();
        bufCtx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
        bufCtx.strokeStyle = "rgb(255, 255, 255)";
        bufCtx.arc(x, y, r, 0, Math.PI * 2);
        bufCtx.stroke();
        bufCtx.fill();
        bufCtx.closePath();
    }

    function _draw() {
        let maxSize = canvas.height < canvas.width ? canvas.height : canvas.width;
        let dimen = 8;
        let ox = canvas.width / 2;
        let oy = canvas.height / 2;

        let R1 = maxSize/20;  // 원의 반지름
        let R2 = maxSize/10;  // Y축으로 회전하기 위한 반경

        // 카메라와 스크린의 거리를 z'라 하고, 그 투영되는 상을 x',y'
        // z:x = z':x'
        // z:y = z':y'
        // x' = xz'/z, y' = yz'/z
        // z' = z1
        // x', y' = xz1/z, yz1/z
        // z의 최대거리 z2 = 5000이라 하면
        // x' <= (height/2 * 0.8) (화면 중앙 위치, 마진 0.1)
        // x 의 최대 값은 R1 + R2
        // x' = Z1(R1+R2)/z2 = height * 0.4
        // Z1 = Z2 * height * 0.4 / (R1+R2)

        let ZZ2 = 5000;
        let ZZ1 = maxSize * ZZ2 * 0.4 / (R1 + R2);

        let points = [];

        for (let i = 0; i < 628; i += dimen) {
            let x1 = Math.cos(i/100) * R1 + R2;
            let y1 = Math.sin(i/100) * R1;
            let nx1 = Math.cos(i/100);
            let ny1 = Math.sin(i/100);

            for (let j = 0; j < 628; j += dimen) {
                // Y축 회전
                let x2 = x1 * Math.cos(j/100);
                let y2 = y1;
                let z2 = x1 * Math.sin(j/100);

                let nx2 = nx1 * Math.cos(j/100);
                let ny2 = ny1;
                let nz2 = nx1 * Math.sin(j/100);

                // X축 회전
                let x3 = x2;
                let y3 = y2 * Math.cos(thetaX/100) - z2 * Math.sin(thetaX/100);
                let z3 = y2 * Math.sin(thetaX/100) + z2 * Math.cos(thetaX/100);

                let nx3 = nx2;
                let ny3 = ny2 * Math.cos(thetaX/100) - nz2 * Math.sin(thetaX/100);
                let nz3 = ny2 * Math.sin(thetaX/100) + nz2 * Math.cos(thetaX/100);

                // Z축 회전
                let x4 = x3 * Math.cos(thetaZ/100) - y3 * Math.sin(thetaZ/100);
                let y4 = x3 * Math.sin(thetaZ/100) + y3 * Math.cos(thetaZ/100);
                let z4 = ZZ2 + z3;

                let nx4 = nx3 * Math.cos(thetaZ/100) - ny3 * Math.sin(thetaZ/100);
                let ny4 = nx3 * Math.sin(thetaZ/100) + ny3 * Math.cos(thetaZ/100);
                let nz4 = nz3;

                // 법선 벡터 (nx4, ny4, nz)와 광원의 백터 내적 계산
                // 광원 위치는 (0, 0, -1)
                let lx = 0;
                let ly = 0;
                let lz = -1;
                let light = nx4 * lx + ny4 * ly + nz4 * lz;

                if (light > 0) {
                    let color = Math.round(light * 255);

                    // x' = xz'/z, y' = yz'/z
                    let xp = Math.floor(x4 * ZZ1 / z4);
                    let yp = Math.floor(-y4 * ZZ1 / z4);

                    points.push([xp + ox, yp + oy, 255-color]);
                }
            }
        }

        bufCtx.beginPath();
        bufCtx.strokeStyle = "black";
        bufCtx.fillStyle = "black";
        bufCtx.fill();

        bufCtx.fillRect(0, 0, canvas.width, canvas.height);
        bufCtx.closePath();
        bufCtx.stroke();

        points.forEach(e => drawCircle(e[0], e[1], e[2], 1));

        thetaX = (thetaX + 2) % 629;
        thetaZ = (thetaZ + 2) % 629;
    }

    function OnDraw() {
        _draw();

        cvs.beginPath();
        cvs.clearRect(0, 0, canvas.width, canvas.height);
        cvs.drawImage(bufCanvas, 0, 0);

        console.log(">OnDraw()");
    }


    function onLoadPage() {
        InitCanvas();
        OnDraw();
        setInterval(OnDraw, 50);
    }

    window.onload = onLoadPage();
</script>
</body>
</html>

 

 

Posted by chobocho