Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.05.2012, 17:38   #1
niki_bleak
Новичок
Джуниор
 
Регистрация: 14.05.2012
Сообщений: 4
По умолчанию Редактирование многоугольника и нахождение меньшего угла

Написать программу графического ввода и редактирования ломанной (многоугольника) на PaintBox. Программа должна иметь следующие функции:
- пользователь нажал левую кнопку мыши – нарисовалась точка; еще одно нажатие приводит к рисованию еще одной точки и линии соединяющей две точки и т.д. (в задачах с многоугольником первая и последняя точки должны совпадать).
- пользователь нажал правую кнопку мыши ( с нажатием клавиши клавиатуры) – должна выполниться одна из операций (в зависимости от клавиши):
- удаление точки на которой стоит курсор;
- добавление точки на отрезок к которому эта точка ближе всего;
- перемещение существующей точки.
- Выделить самый маленький внутренний угол выпуклого многоугольника.

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Math;

type
  TForm1 = class(TForm)
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormPaint(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

type TPoints = array of TPoint;

const
  tolerance = 10;//расстояние в пикселях, при котором две точки сольются в одну

var
  Form1: TForm1;
  Done:boolean;//true, если многоугольник создан
  p:TPoints;//массив точек
  count,selindex:integer;
  ShiftDown,CtrlDown,move,select:boolean;
implementation

{$R *.dfm}

procedure PaintPoly(Canvas:TCanvas;points:array of tpoint);
var i:integer;
min,r:real;
p1:TPoint;
x1,x2,y1,y2:Real;
begin
   min:=360;
   Canvas.Pen.Color:=clgreen;
   Canvas.Pen.Width:=2;
   Canvas.Brush.Color := clBtnFace;
   Canvas.FillRect(Canvas.ClipRect);
   for i:=0 to high(points)-1 do begin
      Canvas.MoveTo(points[i].X,points[i].Y);
      Canvas.LineTo(points[i+1].X,points[i+1].Y);
      form1.Canvas.Ellipse(points[i].X-3,points[i].Y-3,points[i].X+3,points[i].Y+3);
   end;

   for i:=1 to high(points)-1 do begin

           x1:=points[i+1].X-points[i].X;
           x2:=points[i-1].X-points[i].X;
           y1:=points[i+1].Y-points[i].Y;
           y2:=points[i-1].Y-points[i].Y;
           r:=arctan(((sqr(x1)+sqr(y1))*(sqr(x2)+sqr(y2))/sqr(x1*x2+y1*y2))-1);
           r:=RadToDeg(r);
           if r<min then begin
             min:=r;
             p1:=points[i];

           end;

   end;
   if high(points)>=4 then begin
     Canvas.Brush.Color := clred;
     Canvas.Ellipse(p1.X-5,p1.Y-5,p1.X+5,p1.Y+5);

   end;

end;

function distance(p1,p2:TPoint;x,y:integer):real;//расстояние от точки до отрезка
var left,right:real;
begin
    left:=sqrt(sqr(x-p1.X)+sqr(y-p1.Y));
    right:=sqrt(sqr(x-p2.X)+sqr(y-p2.Y));
    result:=left;
    if right<result then result:=right;
end;

function AddPoint(points:TPoints;x,y:integer):TPoints;//добавление точки в массив
var i,count,index:integer;
min,r:real;
begin
   min:=1000000;
   count:=0;
   SetLength(Result,length(points)+1);
   for i:=0 to high(Points)-1 do begin
       r:=distance(points[i],points[i+1],x,y);
       if r<min then begin
          min:=r;
          index:=i;
       end;
   end;
   for i:=0 to high(points) do begin
       Result[count]:=points[i];
       count:=count+1;
       if i=index then begin
           Result[count].X:=x;
           Result[count].Y:=y;
           count:=count+1;
       end;
   end;
end;

Последний раз редактировалось niki_bleak; 14.05.2012 в 17:45.
niki_bleak вне форума Ответить с цитированием
Старый 14.05.2012, 17:41   #2
niki_bleak
Новичок
Джуниор
 
Регистрация: 14.05.2012
Сообщений: 4
По умолчанию

Код:
function DelPoint(points:TPoints;index:integer):TPoints;//удалени точки из массива точек многоугольника
var i,count:integer;
begin
  if Length(points)>=5 then begin
     count:=0;
     SetLength(Result,Length(points)-1);
     for i:=0 to High(points) do begin
        if i<>index then begin
            Result[count]:=points[i];
            count:=count+1;
        end;
     end;
     if index=0 then Result[count-1]:=Result[0];
  end else begin
     Result:=points;
  end;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var i:integer;
begin
   select:=false;
   //построение многоугольника
   if (not Done)and(Button = mbleft) then begin
       SetLength(p,count+1);
       if count<>0 then begin
          if (sqrt(sqr(x-p[0].X)+sqr(y-p[0].Y))<=tolerance)and(count>3) then begin
             p[count]:=p[0];
             form1.Canvas.Ellipse(p[0].X-3,p[0].Y-3,p[0].X+3,p[0].Y+3);
             form1.Canvas.MoveTo(p[count-1].X,p[count-1].Y);
             form1.Canvas.LineTo(p[0].X,p[0].Y);
             Done:=true;
             PaintPoly(form1.Canvas,p);
          end else begin
             p[count].X:=x;
             p[count].Y:=y;
             form1.Canvas.Ellipse(x-3,y-3,x+3,y+3);
             form1.Canvas.MoveTo(p[count-1].X,p[count-1].Y);
             form1.Canvas.LineTo(x,y);
          end;
       end else begin
             p[count].X:=x;
             p[count].Y:=y;
             form1.Canvas.Ellipse(x-3,y-3,x+3,y+3);
       end;
       count:=count+1;
   end;
   //выбор точки
   if Done then for i:=0 to high(p) do begin
       if sqrt(sqr(x-p[i].X)+sqr(y-p[i].Y))<=tolerance then begin
           select:=true;
           selindex:=i;
           if Button = mbLeft then move:=true;
           break;
       end;
   end;


end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   Done:=false;
   form1.Canvas.Pen.Color:=clgreen;
   form1.Canvas.Pen.Width:=2;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
	If (key = vk_Shift) then
		 ShiftDown := true;
	If (key = vk_Control) then
		 CtrlDown:= true;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
   if Move then begin
       if selindex=0 then begin
          p[0].X:=x;
          p[0].Y:=y;
          p[high(p)].X:=x;
          p[high(p)].Y:=y;
       end else begin
          p[selindex].X:=x;
          p[selindex].Y:=y
       end;
       PaintPoly(form1.Canvas,p);
   end;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   Move:=false;
   //удаление точки
   if select and CtrlDown and (Button = mbRight) then begin
       p:=DelPoint(p,selindex);
       PaintPoly(form1.Canvas,p);
   end;
   //добавление точки
   if Done and ShiftDown and (Button = mbRight) then begin
       p:=AddPoint(p,x,y);
       PaintPoly(form1.Canvas,p);
   end;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   ShiftDown:=false;
   CtrlDown:=false;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  if Done then PaintPoly(form1.Canvas,p);
end;

end.
Проблема с нахождением меньшего угла. После того как нарисована фигура не правильно находится угол и вылетает ошибка.
Подскажите что не так.
niki_bleak вне форума Ответить с цитированием
Старый 14.05.2012, 17:49   #3
denisbrain
Форумчанин
 
Регистрация: 29.05.2011
Сообщений: 449
По умолчанию

Код:
uses math;
Function Ugol(a,b:Tpoint):real;
var Ch:integer;
begin
  result:=arctan2((a.y-b.y),(a.x-b.x));
end;
задания на pascal/delphi ICQ 368254335
Tel +79177425326 mail denis-naymov1985(at)mail.ru login skype denis.new.skype
denisbrain вне форума Ответить с цитированием
Старый 14.05.2012, 18:16   #4
niki_bleak
Новичок
Джуниор
 
Регистрация: 14.05.2012
Сообщений: 4
По умолчанию

мне не понятно, между чем и чем находит угол arctan2?
niki_bleak вне форума Ответить с цитированием
Старый 14.05.2012, 18:31   #5
denisbrain
Форумчанин
 
Регистрация: 29.05.2011
Сообщений: 449
По умолчанию

угол наклона прямой
задания на pascal/delphi ICQ 368254335
Tel +79177425326 mail denis-naymov1985(at)mail.ru login skype denis.new.skype
denisbrain вне форума Ответить с цитированием
Старый 14.05.2012, 18:39   #6
niki_bleak
Новичок
Джуниор
 
Регистрация: 14.05.2012
Сообщений: 4
По умолчанию

а как найти угол между двумя прямыми?
niki_bleak вне форума Ответить с цитированием
Старый 14.05.2012, 19:19   #7
Rin
Негодник
Форумчанин
 
Аватар для Rin
 
Регистрация: 10.11.2009
Сообщений: 880
По умолчанию

Угол в градусах между двумя отрезками
Код:
arccos(  (x1*x2+y1*y2)  /   (sqrt(sqr(x1)+sqr(y1))*sqrt(sqr(x2)+sqr(y2)))  )*180/pi
где x1,y1,x2,y2 - направляющие вектора.

Вот ещё вариант, предложенный amk с другого форума:

Цитата:
dx1 = x1 - x2
dy1 = y1 - y2
dx2 = x3 - x2
dy2 = y3 - y2

a = dx1*dy2 - dy1*dx2
b = dx1*dx2 + dy1*dy2

θ = arctan(a/b)
Угол будет в радианах. Усножишь на 180/pi и получишь в градусах.
Если помог, проси поставить минус. Будь оригинален!

Последний раз редактировалось Rin; 14.05.2012 в 20:47.
Rin вне форума Ответить с цитированием
Старый 15.05.2012, 07:05   #8
denisbrain
Форумчанин
 
Регистрация: 29.05.2011
Сообщений: 449
По умолчанию

Цитата:
Сообщение от Rin Посмотреть сообщение
Угол в градусах между двумя отрезками
Код:
arccos(  (x1*x2+y1*y2)  /   (sqrt(sqr(x1)+sqr(y1))*sqrt(sqr(x2)+sqr(y2)))  )*180/pi
где x1,y1,x2,y2 - направляющие вектора.

Вот ещё вариант, предложенный amk с другого форума:


Угол будет в радианах. Усножишь на 180/pi и получишь в градусах.
т.е. в данном случаи оба отрезка задаются координатами ?
AB(x1,y1,x2,y2)
BC(x2,y2,x3,y3) ???
задания на pascal/delphi ICQ 368254335
Tel +79177425326 mail denis-naymov1985(at)mail.ru login skype denis.new.skype
denisbrain вне форума Ответить с цитированием
Старый 15.05.2012, 16:30   #9
Rin
Негодник
Форумчанин
 
Аватар для Rin
 
Регистрация: 10.11.2009
Сообщений: 880
По умолчанию

Да, задаются координатами . В любом из двух случаев ищем направляющие вектора.
Кстати, может вылететь ошибка "Devision by zero". Так что проверяйте делители, и если что подставляйте БМВ.
Если помог, проси поставить минус. Будь оригинален!
Rin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Найти расстояние от верхнего левого угла до правого нижнего угла матрицы iMisha Паскаль, Turbo Pascal, PascalABC.NET 3 03.04.2012 22:19
Нахождение углов произвольного многоугольника. KoPPeW Общие вопросы C/C++ 7 16.11.2011 18:31
Нахождение тангенса угла. mosk3 Общие вопросы Delphi 0 08.09.2010 21:31
Нахождение тангенса угла наклона (С++) decompressed Помощь студентам 5 31.01.2010 20:06