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

Вход на сайт

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

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

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

Спасибо за реализацию, она действительно быстрая. Но не все линии отрисовывает в нужную сторону... Необходимо добавить проверку для случая X-линии if(y1 "<" y0) grad=-grad; и аналогично для Y-линии if(x1 "<" x0) grad=-grad; P.S. На...
Отличные уроки(учу GL по ним), только в renderScene нужно добавить очистку буфера цвета и буфера глубины. При изменении размеров треугольники размножаются)
как исправить это , сделал все по инструкции
Timer1 - выдает ошибку. Использовал IdleTimer1, работает! unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, OpenGLContext, GL, GLU; type { TForm1 } TForm1 =...
в коде присутствуют ошибки! // Считываем координаты procedure TForm1.getCoords(Sender: TObject); var j1:longint; begin n:= StrToInt(Edit2.Text); //число точек s1:=Edit1.Text; s2:=''; i := 1; j:=1; k:=0...

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

Яндекс.Метрика Рейтинг@Mail.ru
Скриншот к примеру
Среда программирования: 
CodeBlocks 13.12
Статья по теме: 

Вход : множество точек, представляющих полигон в порядке обхода вершин в любом направлении.
Результат : определение типа полигона (выпуклый; не выпуклый).

Как использовать.
Набросать левой клавишей мыши (ЛКМ) вершины:
вид до проверки

Нажать правую клавишу мыши(ПКМ), произойдет проверка.
Результат может быть таким:
выпуклый полигон

или таким:
 не выпуклый полигон

Проверка основывается на том факте, что у выпуклого полигона все повороты смежных ребер одного знака.

Код программы: 

// пример работы с векторным произведением
 
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
 
#include <iostream>     // удобно для отладки
 
void handleMouseLeft(sf::VertexArray& pVertex, sf::Vector2i iCurrPos, sf::Text& pText, sf::ConvexShape& polygon);
void handleMouseRight(sf::VertexArray& pVertex, sf::Text& pText, sf::ConvexShape& polygon);
bool isConvexPolygon(const sf::VertexArray& mVertex);
int getSignVertex(sf::Vertex fVertex1, sf::Vertex fVertex2, sf::Vertex fVertex);
 
bool polygonCheked = false;
 
int main()
{
    // без кнопки максимизации
    sf::RenderWindow window(sf::VideoMode(640, 480), "is convex polygon",
                            sf::Style::Close|sf::Style::Titlebar);
 
    // LinesStrip - связывать 2 рядом идущие точки линией
    sf::VertexArray lines(sf::LinesStrip, 0);
 
    sf::ConvexShape polygon;
    polygon.setFillColor(sf::Color::Cyan);
    polygon.setOutlineThickness(2);
    polygon.setOutlineColor(sf::Color::Green);
 
    sf::Font font;
    font.loadFromFile("Sansation.ttf");
 
    // ЛКМ - набрасывание точек;  ПКМ - построение
    sf::Text mText("LKM - nabrasyvaniye tochek;   PKM - postroeniye", font, 20);
    mText.setPosition(5.f, 425.f);
    mText.setColor(sf::Color::Cyan);
 
    // полигон не определен
    sf::Text mTextIs("polygon not defined", font, 20);
    mTextIs.setPosition(5.f, 450.f);
    mTextIs.setColor(sf::Color::Cyan);
 
    while (window.isOpen())     // цикл опроса событий
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            // ЛКМ
            if ((event.type == sf::Event::MouseButtonPressed) &
                    (sf::Mouse::isButtonPressed(sf::Mouse::Left)) )
                {
                    sf::Vector2i iCurrPos = sf::Mouse::getPosition(window) ;
                    handleMouseLeft(lines, iCurrPos, mTextIs, polygon);
                }
            // ПКМ
            if ((event.type == sf::Event::MouseButtonPressed) &
                    (sf::Mouse::isButtonPressed(sf::Mouse::Right)) )
                handleMouseRight(lines, mTextIs, polygon);
        }
        window.clear();
        window.draw(lines);
        window.draw(polygon);
        window.draw(mText);
        window.draw(mTextIs);
        window.display();
    }
}
 
void handleMouseLeft(sf::VertexArray& pVertex, sf::Vector2i iCurrPos,
                     sf::Text& pText, sf::ConvexShape& polygon)
{
    // если новое ипользование
    if (polygonCheked) {
        pVertex.clear();
        pText.setColor(sf::Color::Cyan);
        pText.setString("polygon not defined");
        polygon.setPointCount(0);
        polygonCheked = false;
    }
    // VertexArray - только float (кроссплатформенность),
    // sf::Mouse::getPosition(window) - pair<int>
    sf::Vector2f fCurrPos(0.0 + iCurrPos.x, 0.0 + iCurrPos.y);
    // sf::VertexArray.append принимает вектор с float значениями; кроссплатформенность
    pVertex.append(fCurrPos);
};
 
void handleMouseRight(sf::VertexArray& lines, sf::Text& pText, sf::ConvexShape& polygon)
{
    polygonCheked = true;
    if (isConvexPolygon(lines) ) {
        pText.setString("convex polygon");
        pText.setColor(sf::Color::Green);
        polygon.setPointCount(lines.getVertexCount());
        sf::Vector2f fVector;
        for (unsigned int i = 0; i < lines.getVertexCount(); i++){
            fVector.x = lines[i].position.x;
            fVector.y = lines[i].position.y;
            polygon.setPoint(i, fVector);
        }
        lines.clear();
    }
    else {
        pText.setColor(sf::Color::Red);
        pText.setString("not convex polygon");
    }
    // добавляем ребро к начальной точке
    lines.append(lines[0]);
};
 
// Вход     : множество вершин в порядке обхода в любом направлении
// Выход    : булево-значение [выпуклый <--> не выпуклый]
bool isConvexPolygon(const sf::VertexArray& pVertex)
{
    bool bRetVal = false;
    int signPrime = 0;
    int iVertexCount = pVertex.getVertexCount();
    // взять первый ненулевой знак, если 0 - вернуть false
    int i = 0;  // vertex 'iterator'
    for ( ; i < iVertexCount; ++i) {
        // getSignVertex(vertex[i], vertex[i+1], vertex[i+2]) ; n+2=2
        // нет оператора присваивания: xxx = pVertex[i] ,
        // выдержка: Vertex &  operator[] (unsigned int index)
        //           sf::Vertex::Vertex  ( const Vector2f &  thePosition )
        signPrime = getSignVertex(  pVertex[i],
                                    pVertex[(i+1)%iVertexCount],
                                    pVertex[(i+2)%iVertexCount]);
        if (signPrime != 0) break;
    } // for
    if (signPrime == 0) return bRetVal;  // линия
    // сравниваем остальные знаки с образцом
    for ( ; i < iVertexCount; ++i) {
        int signNext = getSignVertex(pVertex[i],
                                     pVertex[(i+1)%iVertexCount],
                                     pVertex[(i+2)%iVertexCount]);
        // если знаки разные
        if ( (signNext != signPrime) & (signNext != 0) ) {
            return bRetVal;
        } // if
    }
    bRetVal = true;
    return bRetVal;
};
 
// вычисление знака угла поворота
// возврат -1, 0, 1
int getSignVertex(sf::Vertex fVertex1, sf::Vertex fVertex2, sf::Vertex fVertex3)
{
    // уравнение прямой ab: Ax + By + C = 0;
    //  A = a.y-b.y, B = b.x-a.x, C = -(a.x*A + a.y*B)
    // площадь на основе векторов ab и ac
    float fArea = ( (fVertex2.position.x - fVertex1.position.x)*
                    (fVertex3.position.y - fVertex1.position.y) -
                    (fVertex3.position.x - fVertex1.position.x)*
                    (fVertex2.position.y - fVertex1.position.y) );
    int iRetVal = 0;
    if (fArea == 0) return iRetVal;
    iRetVal  = (fArea > 0) ? 1 : -1;
    return iRetVal;
};

Прикрепленный файлРазмер
isConvex.rar477.16 кб
source_is_convex.rar13.91 кб