Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

Выдаёт ошибку glut32.dll не найден! При том, что он лежит в System32! Всё решил) Нужно отправить не в System32, а в System.
Спасибо за статью. Я не Ваш студент. Но мне она помогла написать функцию для Канторова множества на Python для черепашки: import turtle def kanter(x, y, d):     if d > 1:         turtle...
Как реализовать в данном примере границы расчёта?

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Демо JavaScript: 

<canvas id = "canvas" width = "500" height = "500"></canvas><br>
 
<div>
    <select id = "select">
        <option value = "0"> Heart 1 </option>
        <option value = "1"> Heart 2 </option>
        <option value = "2"> Star    </option>
        <option value = "3"> Square  </option>
        <option value = "4"> Arrow   </option>
    </select>
    <button onclick = "init()"> Select </button>
</div>
 
<script>
    /***** Canvas *****/
    let canvas = document.querySelector("canvas");
    let ctx = canvas.getContext("2d");
    let canvasWidth = canvas.width;
    let canvasHeight = canvas.height;
    let canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
 
    // Обновляем canvas
    function updateCanvas() {
        ctx.putImageData(canvasData, 0, 0);
    }
 
    /***** Графическая библиотека *****/
    // Рисуем пиксель
    function drawPixel(x, y, color = {r: 255, g: 0, b: 0, a: 255}) {
        const index = (x + y * canvasWidth) * 4;
        canvasData.data[index + 0] = color.r;
        canvasData.data[index + 1] = color.g;
        canvasData.data[index + 2] = color.b;
        canvasData.data[index + 3] = color.a;
        return color;
    }
 
    // Рисуем отрезок по алгоритму Брезенхема
    function drawLine(x1, y1, x2, y2, color = {r: 255, g: 0, b: 0, a: 255}) {
        const deltaX = Math.abs(x2 - x1);
        const deltaY = Math.abs(y2 - y1);
 
        const signX = x1 < x2 ? 1 : -1;
        const signY = y1 < y2 ? 1 : -1;
 
        let error = deltaX - deltaY;
        drawPixel(x2, y2, color);
 
        while (x1 !== x2 || y1 !== y2) {
            drawPixel(x1, y1, color);
            let error2 = error * 2;
 
            if (error2 > -deltaY) {
                error -= deltaY;
                x1 += signX;
            }
            if (error2 < deltaX) {
                error += deltaX;
                y1 += signY;
            }
        }
    }
 
    // Рисуем треугольник
    function drawTriangle(x1, y1, x2, y2, x3, y3, color = {r: 255, g: 0, b: 0, a: 255}) {
        drawLine(x1, y1, x2, y2, color);
        drawLine(x2, y2, x3, y3, color);
        drawLine(x3, y3, x1, y1, color);
    }
 
    // Рисуем многоугольник
    function drawPolygon(color =  {r: 0, g: 0, b: 0, a: 255}) {
        for (let i = 0; i < polygon.length; i++) {
            const newI = (i + 1 === polygon.length ? 0 : i + 1);
            drawLine(polygon[i].x, polygon[i].y, polygon[newI].x, polygon[newI].y, color);
        }
    }
 
    // Получаем цвет пикселя
    function getColor(x, y) {
        const index = (x + y * canvasWidth) * 4;
        const r = canvasData.data[index + 0];
        const g = canvasData.data[index + 1];
        const b = canvasData.data[index + 2];
        const a = canvasData.data[index + 3];
        return {r: r, g: g, b: b, a: a};
    }
 
    // Заливка 4-х связным алгоритмом
    function fill(x, y, color = {r: 255, g: 0, b: 0, a: 255}) {
        let startColor = getColor(x, y);
 
        if (startColor.r === color.r &&
            startColor.g === color.g &&
            startColor.b === color.b &&
            startColor.a === color.a) {
            return;
        }
 
        let q = [{x: x, y: y}];
        for (let i = 0; i !== q.length; i++) {
            let x = q[i].x, y = q[i].y;
 
            let newColor = getColor(x, y);
            if (x >= 0 && y >= 0 && x < canvasWidth && y < canvasHeight && newColor.r === startColor.r
                && newColor.g === startColor.g && newColor.b === startColor.b && newColor.a === startColor.a) {
                newColor = drawPixel(x, y, color);
 
                let length = q.length;
                q[length + 0] = {x: x + 1, y: y};
                q[length + 1] = {x: x - 1, y: y};
                q[length + 2] = {x: x, y: y + 1};
                q[length + 3] = {x: x, y: y - 1};
            }
        }
    }
 
    // Заливка прямоугольника
    function fillRectangle(x1, y1, width, height, color = {r: 255, g: 0, b: 0, a: 255}) {
        for (let i = y1; i <= y1 + height; i++) {
            drawLine(x1, i, x1 + width, i, color);
        }
    }
 
    /***** Создаем многоулогьник *****/
    // Описываем точку
    class Point {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
    }
 
    // Многоугольник
    let polygon = [];
 
    // Заполняем массив polygon
    function createPolygon() {
        polygon = [];
        fillRectangle(0, 0, canvasWidth, canvasHeight, {r: 142, g: 67, b: 231, a: 255});
 
        const selectValue = parseInt(document.getElementById("select").value);
 
        let xC = Math.floor(canvasWidth / 2), yC =  Math.floor(canvas.height / 2);
        switch (selectValue) {
            case 0:
                // Polygon 1
                polygon.push(new Point(xC +  0, yC - 40 -  0));
 
                // left
                polygon.push(new Point(xC - 20, yC - 40 - 20));
                polygon.push(new Point(xC - 40, yC - 40 - 30));
                polygon.push(new Point(xC - 60, yC - 40 - 30));
                polygon.push(new Point(xC - 80, yC - 40 - 20));
                polygon.push(new Point(xC - 90, yC - 40 -  0));
                polygon.push(new Point(xC - 90, yC - 40 + 20));
                polygon.push(new Point(xC - 80, yC - 40 + 50));
 
                polygon.push(new Point(xC -  0, yC - 40 + 140));
 
                // right
                polygon.push(new Point(xC + 80, yC - 40 + 50));
                polygon.push(new Point(xC + 90, yC - 40 + 20));
                polygon.push(new Point(xC + 90, yC - 40 -  0));
                polygon.push(new Point(xC + 80, yC - 40 - 20));
                polygon.push(new Point(xC + 60, yC - 40 - 30));
                polygon.push(new Point(xC + 40, yC - 40 - 30));
                polygon.push(new Point(xC + 20, yC - 40 - 20));
                break;
            case 1:
                // Polygon 2
                polygon.push(new Point(xC -  0, yC - 40 + 140));
 
                // right
                polygon.push(new Point(xC + 80, yC - 40 + 50));
                polygon.push(new Point(xC + 90, yC - 40 + 20));
                polygon.push(new Point(xC + 90, yC - 40 -  0));
                polygon.push(new Point(xC + 80, yC - 40 - 20));
                polygon.push(new Point(xC + 60, yC - 40 - 30));
                polygon.push(new Point(xC + 40, yC - 40 - 30));
                polygon.push(new Point(xC + 20, yC - 40 - 20));
 
                polygon.push(new Point(xC +  0, yC - 40 -  0));
 
                // left
                polygon.push(new Point(xC - 20, yC - 40 - 20));
                polygon.push(new Point(xC - 40, yC - 40 - 30));
                polygon.push(new Point(xC - 60, yC - 40 - 30));
                polygon.push(new Point(xC - 80, yC - 40 - 20));
                polygon.push(new Point(xC - 90, yC - 40 -  0));
                polygon.push(new Point(xC - 90, yC - 40 + 20));
                polygon.push(new Point(xC - 80, yC - 40 + 50));
                break;
            case 2:
                // Polygon 3
                let x, y, radius = 200;
                for (let angle = 18; angle <= 360; angle += 72) {
                    x = Math.floor(xC + radius * Math.cos(angle * Math.PI / 180));
                    y = Math.floor(yC - radius * Math.sin(angle * Math.PI / 180));
                    polygon.push(new Point(x, y));
                    x = Math.floor(xC + radius * 2 / 5 * Math.cos((angle + 36) * Math.PI / 180));
                    y = Math.floor(yC - radius * 2 / 5 * Math.sin((angle + 36) * Math.PI / 180));
                    polygon.push(new Point(x, y));
                }
                break;
            case 3:
                // Polygon 4
                polygon.push(new Point(xC + 80, yC - 80));
                polygon.push(new Point(xC - 80, yC - 80));
                polygon.push(new Point(xC - 80, yC + 80));
                polygon.push(new Point(xC + 80, yC + 80));
                break;
            case 4:
                // Polygon 5
                polygon.push(new Point(xC +  0, yC - 60));
                polygon.push(new Point(xC - 60, yC + 60));
                polygon.push(new Point(xC +  0, yC +  0));
                polygon.push(new Point(xC + 60, yC + 60));
                break;
            default:
                console.log("default", selectValue);
                break;
        }
    }
 
    /***** Триангуляция *****/
    // Считает площадь треугольника
    function calculateSquare(A, B, C) {
        return 1 / 2 * Math.abs((B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y));
    }
 
    // Принадлежит ли точка треугольнику?
    function inTriangle(A, B, C, D) {
        return calculateSquare(A, B, C) === calculateSquare(A, B, D) + calculateSquare(A, C, D) + calculateSquare(B, D, C);
    }
 
    // Левая тройка векторов?
    function isLeft(A, B, C) {
        const AB = {
                x: B.x - A.x,
                y: B.y - A.y
            },
            AC = {
                x: C.x - A.x,
                y: C.y - A.y
            };
 
        return AB.x * AC.y - AC.x * AB.y < 0;
    }
 
    // Есть ли другие точки внутри рассматриваемого треугольника?
    function hasPointOfPolygon(points) {
        const A = points[0],
              B = points[1],
              C = points[2];
 
        for (let p = 3; p < points.length; p++) {
            if (inTriangle(A, B, C, points[p])) return true;
        }
 
        return false;
    }
 
    // Триангуляция
    function triangulate(point = new Point(260, 250), color = {r: 255, g: 255, b: 255, a: 255}) {
        while (polygon.length >= 3) {
            if (isLeft(polygon[0], polygon[1], polygon[2]) && !hasPointOfPolygon(polygon)) {
 
                const x1 = polygon[0].x,
                    y1 = polygon[0].y;
                const x2 = polygon[1].x,
                    y2 = polygon[1].y;
                const x3 = polygon[2].x,
                    y3 = polygon[2].y;
                drawTriangle(x1, y1, x2, y2, x3, y3, color);
 
                if (inTriangle(polygon[0], polygon[1], polygon[2], point)) {
                    let cx = Math.floor((x1 + x2 + x3) / 3);
                    let cy = Math.floor((y1 + y2 + y3) / 3);
                    fill(cx, cy);
                }
 
                polygon.splice(1, 1);
            } else {
                const tmp = polygon[0];
                polygon.shift();
                polygon.push(tmp);
            }
        }
    }
 
    /***** Старт *****/
    // Функция с которой программа начинает работу
    function init() {
        createPolygon();
        drawPolygon();
        triangulate();
        updateCanvas();
    }
</script>