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

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

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

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

У меня проблема вот с этим: gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);. Вылезает ошибка: CS1061 "object" не содержит определения "GL_COLOR_BUFFER_BIT", и не удалось найти доступный метод расширения "GL_COLOR_BUFFER_BIT",...
Большое спасибо. Единственный код который прошел без каких либо ошибок. Ура!!!
Скажите пожалуйста, подскажите алгоритм по которому по заданным точкам можно определить тип многогранника, скажем это куб или прямоугольный параллелепипед. Нашел теорию по этим фигурам: https://www.mat... https://www.mat... Акцентировать внимание...
Всем у кого не работает. файл wizard.script Ещё одно упоминание Glut32 в строке "if (!VerifyLibFile(dir_nomacro_lib, _T("glut32"), _T("GLUT's"))) return false;" меняем на "if (!VerifyLibFile(dir_nomacro_lib, _T("freeglut"), _T("GLUT's"))) return...
Не получается, емаё

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

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

Тест на попадание точки внутрь многоугольника. При нажатии на корпус самолета (серую часть) появляются pepe, летящие вниз.

  let offset = -100;
  let bgColor = '#14142d';
  let bombsFlag = false;
 
  window.addEventListener('load', start);
  document.getElementById('viewport').addEventListener('click', (e) => { // Обработка нажатий на canvas
    let pol = [ // Массив вершин многоугольника, внутрь которого может попасть точка, нужен для передачи в функцию проверки.
      {x: 305 - offset, y: 243},
      {x: 320 - offset, y: 235},
      {x: 340 - offset, y: 234},
 
      {x: 379 - offset, y: 236},
      {x: 397 - offset, y: 231},
      {x: 406 - offset, y: 232},
      {x: 416 - offset, y: 238},
 
      {x: 439 - offset, y: 240},
      {x: 456 - offset, y: 242},
      {x: 472 - offset, y: 226},
      {x: 480 - offset, y: 227},
      {x: 469 - offset, y: 245},
      {x: 469 - offset, y: 253},
      {x: 438 - offset, y: 258},
      {x: 403 - offset, y: 258},
      {x: 364 - offset, y: 258},
      {x: 341 - offset, y: 257},
      {x: 317 - offset, y: 252},
    ];
    if (getPointPosition({x: e.offsetX, y: e.offsetY}, pol) === 1) { // Проверка попадания точки в многоугольник, определенный переменной pol
      bombsFlag = true;
    }
  });
 
  function start() {
    let ctx = document.getElementById('viewport').getContext('2d');
 
    setInterval(() => { // Основная функция отрисовки.
      ctx.fillStyle = "#202d76";
      ctx.fillRect(0, 0, 500, 500); // заливка холста для текущего кадра
 
      if (bombsFlag) {
        drawBombs(ctx);
      }
 
      ctx.fillStyle = "#2e49cd";
      ctx.strokeStyle = "rgba(15,13,58,0.87)";
 
      ctx.beginPath();
 
      // Отрисовка контура самолета
      ctx.moveTo(305 - offset, 243);
      ctx.lineTo(320 - offset, 235);
      ctx.lineTo(340 - offset, 234);
 
      ctx.lineTo(379 - offset, 236);
      ctx.lineTo(397 - offset, 231);
      ctx.lineTo(406 - offset, 232);
      ctx.lineTo(416 - offset, 238);
 
      ctx.lineTo(439 - offset, 240);
      ctx.lineTo(456 - offset, 242);
      ctx.lineTo(472 - offset, 226);
      ctx.lineTo(480 - offset, 227);
      ctx.lineTo(469 - offset, 245);
      ctx.lineTo(469 - offset, 253);
      ctx.lineTo(438 - offset, 258);
      ctx.lineTo(403 - offset, 258);
      ctx.moveTo(364 - offset, 258);
      ctx.lineTo(341 - offset, 257);
      ctx.lineTo(317 - offset, 252);
      ctx.lineTo(305 - offset, 243);
 
      ctx.moveTo(379 - offset, 236);
      ctx.lineTo(380 - offset, 248);
      ctx.lineTo(418 - offset, 249);
      ctx.lineTo(416 - offset, 238);
 
      ctx.moveTo(362 - offset, 236);
      ctx.lineTo(379 - offset, 186);
      ctx.lineTo(385 - offset, 185);
      ctx.lineTo(395 - offset, 187);
      ctx.lineTo(400 - offset, 232);
      ctx.moveTo(369 - offset, 215);
      ctx.lineTo(398 - offset, 215);
      ctx.moveTo(368 - offset, 219);
      ctx.lineTo(398 - offset, 220);
 
 
      ctx.moveTo(404 - offset, 255);
      ctx.lineTo(362 - offset, 254);
      ctx.lineTo(403 - offset, 323);
      ctx.lineTo(416 - offset, 326);
      ctx.lineTo(420 - offset, 324);
      ctx.lineTo(403 - offset, 255);
      ctx.moveTo(377 - offset, 278);
      ctx.lineTo(409 - offset, 279);
      ctx.moveTo(380 - offset, 283);
      ctx.lineTo(410 - offset, 284);
 
      ctx.moveTo(469 - offset, 229);
      ctx.lineTo(458 - offset, 228);
      ctx.lineTo(453 - offset, 242);
 
      ctx.moveTo(455 - offset, 256);
      ctx.lineTo(467 - offset, 273);
      ctx.lineTo(479 - offset, 272);
      ctx.lineTo(469 - offset, 253);
 
      ctx.stroke();
 
      // Заливка самолета цветом
      fill(386 - offset, 201, '#fa4856', ctx);
      fill(379 - offset, 228, '#fa4856', ctx);
      fill(389 - offset, 271, '#fa4856', ctx);
      fill(404 - offset, 300, '#fa4856', ctx);
      fill(460 - offset, 234, '#fa4856', ctx);
      fill(468 - offset, 264, '#fa4856', ctx);
 
      fill(355 - offset, 246, '#414350', ctx);
      fill(391 - offset, 218, '#414350', ctx);
      fill(396 - offset, 282, '#414350', ctx);
 
      fill(382 - offset, 245, '#83b6ed', ctx);
      offset++;
    }, 20);
  }
 
  let started = false, startTick, count = 0, vOffset = 0;
 
  function drawBombs(ctx) { // функция для отрисовки летящих вниз pepe при клике на самолет
    if (!started) {
      started = true;
      startTick = offset;
    }
    let img = document.getElementById('pepe');
    ctx.drawImage(img, 420 - startTick, 300 + vOffset);
    if (offset - startTick > 40) {
      ctx.drawImage(img, 420 - startTick - 40, 300 + vOffset - 40);
    }
    if (offset - startTick > 80) {
      ctx.drawImage(img, 420 - startTick - 80, 300 + vOffset - 80);
    }
    vOffset++;
  }
 
  function getPointPosition(point, polygon) { // функция проверки на принадлежность точки многоугольнику. Возвращает 0 = на границе, 1 = внутри, -1 = снаружи.
    let p = true;
    polygon.forEach((vertex1, index) => {
      let vertex2 = polygon[(index + 1) % polygon.length];
      let pointPos = getEdgePosition(point, vertex1, vertex2);
      if (pointPos === 1) { // касание
        return 0; // на границе
      } else if (pointPos === 2) { // пересечение границы
          p = !p;
      }
    });
    return p ? -1 : 1;
  }
 
  function getEdgePosition(point, a, b) { // вспомогательная функция, проверка, как соотносится точка с ребром ab
    switch (getPointToEdgePosition(point, a, b)) {
      case 0:
        if ((a.x < point.y) && (point.x <= b.y)) {
          return 2; // пересечение
        } else {
          return 0;
        }
      case 1:
        if ((b.y < point.y) && (point.y <= a.y)) {
          return 2;
        } else {
          return 0;
        }
      case 2:
        return 1; // касание
      default:
        return 0;
    }
  }
 
  function getPointToEdgePosition(point, v, w) { // вспомогательная функция, проверка положения точки относительно отрезка
    let a = v.y - w.y, b = w.x - v.x, c = v.x * w.y - w.x * v.y;
 
    let y = a * point.x + b * point.y + c;
    if (y > 0)
      return 1; // точка справа
    if (y < 0)
      return 0; // точка слева
 
    let minX = Math.min(v.x, w.x), maxX = Math.max(v.x, w.x), minY = Math.min(v.y, w.y), maxY = Math.max(v.y, w.y);
 
    if (minX <= point.X && point.X <= maxX && minY <= point.Y && point.Y <= maxY) {
      return 2; // точка на отрезке
    } else {
      return 3;
    }
  }
 
  function fill(startX, startY, fillColor, ctx) { // функция (относительно) быстрой заливки замкнутого контура
    let pixelStack = [[startX, startY]];
    let canvasWidth = ctx.canvas.width, canvasHeight = ctx.canvas.height, drawingBoundTop = 0;
    let colorLayer = ctx.getImageData(0, 0, 500, 500);
    let startPixel = ctx.getImageData(startX, startY, 1, 1).data;
    //console.log(fillColor, fillColor.substring(1, 3), parseInt('0x' + fillColor.substring(1, 3)), parseInt('0x' + fillColor.substring(3, 5)), parseInt('0x' + fillColor.substring(5, 7)));
 
    while(pixelStack.length)
    {
      let newPos, x, y, pixelPos, reachLeft, reachRight;
      newPos = pixelStack.pop();
      x = newPos[0];
      y = newPos[1];
 
      pixelPos = (y*canvasWidth + x) * 4;
      while(y-- >= drawingBoundTop && matchStartColor(pixelPos, colorLayer, startPixel[0], startPixel[1], startPixel[2]))
      {
        pixelPos -= canvasWidth * 4;
      }
      pixelPos += canvasWidth * 4;
      ++y;
      reachLeft = false;
      reachRight = false;
      while(y++ < canvasHeight-1 && matchStartColor(pixelPos, colorLayer, startPixel[0], startPixel[1], startPixel[2]))
      {
        colorLayer = colorPixel(pixelPos, colorLayer, parseInt('0x' + fillColor.substring(1, 3)), parseInt('0x' + fillColor.substring(3, 5)), parseInt('0x' + fillColor.substring(5, 7)));
 
        if(x > 0)
        {
          if(matchStartColor(pixelPos - 4, colorLayer, startPixel[0], startPixel[1], startPixel[2]))
          {
            if(!reachLeft){
              pixelStack.push([x - 1, y]);
              reachLeft = true;
            }
          }
          else if(reachLeft)
          {
            reachLeft = false;
          }
        }
 
        if(x < canvasWidth-1)
        {
          if(matchStartColor(pixelPos + 4, colorLayer, startPixel[0], startPixel[1], startPixel[2]))
          {
            if(!reachRight)
            {
              pixelStack.push([x + 1, y]);
              reachRight = true;
            }
          }
          else if(reachRight)
          {
            reachRight = false;
          }
        }
 
        pixelPos += canvasWidth * 4;
      }
    }
    ctx.putImageData(colorLayer, 0, 0);
  }
 
  function matchStartColor(pixelPos, colorLayer, startR, startG, startB) // вспомогательная функция для заливки
  {
    let r = colorLayer.data[pixelPos];
    let g = colorLayer.data[pixelPos+1];
    let b = colorLayer.data[pixelPos+2];
 
    return (r === startR && g === startG && b === startB);
  }
 
  function colorPixel(pixelPos, colorLayer, fillColorR, fillColorG, fillColorB) // вспомогательная функция для заливки
  {
    colorLayer.data[pixelPos] = fillColorR;
    colorLayer.data[pixelPos+1] = fillColorG;
    colorLayer.data[pixelPos+2] = fillColorB;
    colorLayer.data[pixelPos+3] = 255;
    return colorLayer;
  }