П.3.1. Текст модуля lineseg.h

//---------------------------------------------------------------------------

 

#ifndef LineSegH

#define LineSegH

//---------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <ActnList.hpp>

#include <Menus.hpp>

#include <Dialogs.hpp>

#include <Graphics.hpp>

#include <ExtCtrls.hpp>

#include <ComCtrls.hpp>

#include <ToolWin.hpp>

#include <ImgList.hpp>

#include <CustomizeDlg.hpp>

//---------------------------------------------------------------------------

class TfrmLineSeg: public TForm

{

__published:   // IDE-managed Components

TStatusBar *sb1;

TPanel *Panel1;

TScrollBox *scb1;

TImage *Image1;

TImage *Image2;

TMainMenu *MainMenu1;

TMenuItem *N1;

TMenuItem *N3;

TMenuItem *N5;

TMenuItem *N4;

TMenuItem *N2;

TMenuItem *N6;

TMenuItem *N10;

TMenuItem *N11;

TMenuItem *N12;

TMenuItem *N1001;

TMenuItem *N10x1;

TMenuItem *N9;

TActionList *ActionList1;

TAction *actExit;

TAction *actOpenFile;

TAction *actSaveFile;

TAction *actNewFile;

TAction *actZoomIn;

TAction *actZoomOut;

TAction *actZoom1;

TAction *actZoom10;

TAction *actAnalyze;

TAction *actGridCheck;

TAction *actLightCheck;

TOpenDialog *OpenDialog1;

TSaveDialog *SaveDialog1;

TImageList *ImageList1;

TCoolBar *CoolBar1;

TToolBar *ToolBar1;

TToolBar *ToolBar2;

TToolBar *ToolBar3;

TToolButton *ToolButton1;

TToolButton *ToolButton2;

TToolButton *ToolButton3;

TToolButton *ToolButton4;

TToolButton *ToolButton5;

TToolButton *ToolButton6;

TToolButton *ToolButton7;

TToolButton *ToolButton8;

TToolButton *ToolButton13;

TToolButton *ToolButton14;

TAction *actLineLightCheck;

TToolButton *ToolButton11;

TToolButton *ToolButton10;

TAction *actSegLightCheck;

TSplitter *Splitter1;

TPanel *Panel2;

TMemo *MemoLog;

TMemo *MemoOut;

TSplitter *Splitter2;

TToolButton *ToolButton12;

TAction *actLockView;

TToolButton *ToolButton16;

TMenuItem *N8;

TMenuItem *N16;

TMenuItem *N17;

TMenuItem *N18;

TToolButton *ToolButton17;

TAction *actAnalyzeNode;

TAction *actAnalyzeSeg;

TToolButton *ToolButton9;

TAction *actMatchLines;

TToolButton *ToolButton18;

TToolButton *ToolButton20;

TAction *actZoomWnd;

TMenuItem *N19;

TToolButton *ToolButton21;

TAction *actMatchOut;

TMenuItem *N7;

TMenuItem *N22;

TAction *actOpenArray;

TAction *actSaveArray;

TMenuItem *N23;

TMenuItem *N24;

TToolButton *ToolButton22;

TToolButton *ToolButton23;

TMemo *mArray;

TAction *actOptions;

TMenuItem *N13;

TToolButton *ToolButton15;

TToolButton *ToolButton19;

TLabel *Label1;

TLabel *Label2;

TToolButton *ToolButton24;

TMenuItem *N14;

TAction *actSaveCode;

TMenuItem *N20;

TToolButton *ToolButton25;

TToolButton *ToolButton26;

TToolButton *ToolButton27;

TAction *actSegCodeOut;

TMenuItem *N15;

void __fastcall actExitExecute(TObject *Sender);

void __fastcall FormCreate(TObject *Sender);

void __fastcall actZoomInExecute(TObject *Sender);

void __fastcall actZoomOutExecute(TObject *Sender);

void __fastcall actOpenFileExecute(TObject *Sender);

void __fastcall actSaveFileExecute(TObject *Sender);

void __fastcall Image2MouseMove(TObject *Sender, TShiftState Shift,

int X, int Y);

void __fastcall Image2MouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y);

void __fastcall actZoom1Execute(TObject *Sender);

void __fastcall actAnalyzeExecute(TObject *Sender);

void __fastcall FormCanResize(TObject *Sender, int &NewWidth,

int &NewHeight, bool &Resize);

void __fastcall actNewFileExecute(TObject *Sender);

void __fastcall actGridCheckExecute(TObject *Sender);

void __fastcall actLightCheckExecute(TObject *Sender);

void __fastcall actZoom10Execute(TObject *Sender);

void __fastcall actLineLightCheckExecute(TObject *Sender);

void __fastcall actSegLightCheckExecute(TObject *Sender);

void __fastcall actLockViewExecute(TObject *Sender);

void __fastcall actAnalyzeNodeExecute(TObject *Sender);

void __fastcall actAnalyzeSegExecute(TObject *Sender);

void __fastcall actMatchLinesExecute(TObject *Sender);

void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);

void __fastcall actZoomWndExecute(TObject *Sender);

void __fastcall actMatchOutExecute(TObject *Sender);

void __fastcall actOpenArrayExecute(TObject *Sender);

void __fastcall actSaveArrayExecute(TObject *Sender);

void __fastcall actOptionsExecute(TObject *Sender);

void __fastcall actSaveCodeExecute(TObject *Sender);

void __fastcall actSegCodeOutExecute(TObject *Sender);

private:  // User declarations

void ZoomTo(double z);

void DrawGrid();

void ShowInfo(int X, int Y);

int __fastcall NeigCount(int x, int y);

int VectMove(int &x, int &y, int vect);

void wlog(AnsiString s);

AnsiString VectToStr(int v);

void ValidateView();

double plDistance(double x,double y,double x1,double y1,double x2,double y2);

// plDistance вычисляет расстояние (минимальное) от точки (x,y)

// до прямой, заданной точками (x1,y1) и (x2,y2)

AnsiString StrToLen(AnsiString str, int len);

// StrToLen возвражает строку длины len

// заполняя пробелями недостающие символы в начале строки str

void __fastcall NeigNode(int x, int y, int n);

// NeigSeg обрабатывает соседей точки (x,y)

// на принадлежность узлу n

// является рекурсивной

void __fastcall NeigLine(int x,int y, int n);

// NeigLine обрабатывает соседей точки (x,y)

// на продолжение линии n

// является рекурсивной

void __fastcall GetLineVect(int x,int y, int n);

// GetLineVect обрабатывает линию в код

// рекурсивная

TPoint NodeCentre(int n);

// NodeCentre возвращает центр узла n (координаты узловой точки)

void __fastcall FillLine(int n1, int n2);

// FillLine присваивает линии n2 пикселы линии n1 (объединение двух линий)

TPoint __fastcall FindMatch(int x, int y);

// FindMatch возвращает точку, соответствующую точке x,y

void __fastcall CodeLine(int x1,int y1,int x2,int y2);

// CodeLine добавляет в глобальную переменную linecode код для отрезка (x1,y1)-(x2,y2)

void __fastcall GetLineVect2(int x,int y, int n);

// GetLineVect2 обрабатывает линию в код

// рекурсивная

public:// User declarations

__fastcall TfrmLineSeg(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TfrmLineSeg *frmLineSeg;

//---------------------------------------------------------------------------

#endif

П.3.2. Текст модуля lineseg.cpp

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "LineSeg.h"

#include "lsImgSize.h"

#include "lsOptions.h"

#include <math.h>

#include <values.h>

#include <io.h>

#include <fcntl.h>

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma link "PERFGRAP"

#pragma resource "*.dfm"

#define min(a, b) (((a) < (b))? (a): (b))

#define max(a, b) (((a) > (b))? (a): (b))

TfrmLineSeg *frmLineSeg;

double zoom,dzoom,maxzoom;

int w,h,def,defh,selline,selnode,oldselline,oldselnode,isnode;

const int maxw=1024,maxh=1024;

TColor c0,c1,c2,c3,c4,c21,c5;

bool logs; // вести журнал вычислений

int nodescnt,xs1,ys1,xs2,ys2,xs3,ys3;

AnsiString linecode; // содержит код текущей линии

// apix[i][j][0] - массив точек

// apix[i][j][1] - массив линий, номер линии

// apix[i][j][2] - массив узлов, номер узла

// -1 - пиксел не обработан, 0 - нет точки, >0 - номер линии, кот. принадлежит точка

// apix[i][j][3] - массив врЕменных атрибутов

int apix[maxw][maxh][4];

//---------------------------------------------------------------------------

__fastcall TfrmLineSeg::TfrmLineSeg(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actExitExecute(TObject *Sender)

{

frmLineSeg->Close();

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::FormCreate(TObject *Sender)

{

scb1->Enabled=false;

logs=true;

zoom=1.0f; dzoom=1.0f;

maxzoom=100.0f;

selline=-1;

Image1->Left=0; Image1->Top=0;

Image2->Left=0; Image2->Top=0;

w=0; h=0;

c0=TColor(RGB(0,0,0)); c1=TColor(RGB(255,255,255));

c2=TColor(RGB(0,255,0)); c3=TColor(RGB(0,0,255));

c4=TColor(RGB(255,0,0)); c21=TColor(RGB(255,255,0));

c5=TColor(RGB(200,200,200));

for(int i=0;i<=maxw-1;i++)

for(int j=0;j<=maxh-1;j++)

{

apix[i][j][0]=0;

apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::FormCloseQuery(TObject *Sender, bool &CanClose)

{

CanClose=MessageBox(Handle,"Выход?", "ЛС", MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)==ID_YES;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoomInExecute(TObject *Sender)

{

zoom+=dzoom;

ZoomTo(zoom);

DrawGrid();

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoomOutExecute(TObject *Sender)

{

if(zoom>dzoom) zoom-=dzoom;

ZoomTo(zoom);

DrawGrid();

}

//---------------------------------------------------------------------------

void TfrmLineSeg::DrawGrid()

{

if(Image2->Visible)

{

Image2->Picture->Bitmap->Width=Image1->Width;

Image2->Picture->Bitmap->Height=Image1->Height;

Image2->Width=Image1->Width;

Image2->Height=Image1->Height;

Image2->Canvas->Pen->Color=c5;

Image2->Canvas->FillRect(Image2->ClientRect);

if(actGridCheck->Checked)

{

for(int i=1;i<=Image2->Height;i++)

{

Image2->Canvas->MoveTo(int(zoom*i),0);

Image2->Canvas->LineTo(int(zoom*i),Image2->Height);

}

for(int i=1;i<=Image2->Width;i++)

{

Image2->Canvas->MoveTo(0,int(zoom*i));

Image2->Canvas->LineTo(Image2->Width,int(zoom*i));

}

}

} // Image2->Visible

}

void __fastcall TfrmLineSeg::actOpenFileExecute(TObject *Sender)

{

OpenDialog1->Title="Открыть изображение";

OpenDialog1->Filter="Файлы изображений (*.bmp)|*.bmp|Все файлы (*.*)|*.*";

if(OpenDialog1->Execute())

{

sb1->SimplePanel=true; sb1->SimpleText="Открытие файла...";

Image1->Picture->LoadFromFile(OpenDialog1->FileName);

Image1->Width=Image1->Picture->Bitmap->Width;

Image1->Height=Image1->Picture->Bitmap->Height;

w=Image1->Picture->Width;

h=Image1->Picture->Height;

scb1->Enabled=true;

ZoomTo(zoom);

for(int i=0;i<=w-1;i++) // maxw-1

for(int j=0;j<=h-1;j++) // maxh-1

{

apix[i][j][0]=Image1->Canvas->Pixels[i][j]==c0?1:0;

apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSaveFileExecute(TObject *Sender)

{

SaveDialog1->Filter="Файлы изображений (*.bmp)|*.bmp|Все файлы (*.*)|*.*";

SaveDialog1->DefaultExt="*.bmp";

SaveDialog1->Title="Сохранить изображение";

if(SaveDialog1->Execute())

{

Image1->Picture->SaveToFile(SaveDialog1->FileName);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::Image2MouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)

{

if (actLockView->Checked) return;

int ix=int(X/zoom),iy=int(Y/zoom);

if(Button==mbLeft)

{

if(Image1->Canvas->Pixels[ix][iy]!=c0)

{

Image1->Canvas->MoveTo(ix,iy);

Image1->Canvas->Pixels[ix][iy]=c0;

apix[ix][iy][0]=1;

}

}

else if(Button==mbRight)

{

if(Image1->Canvas->Pixels[ix][iy]!=c1)

{

Image1->Canvas->MoveTo(ix,iy);

Image1->Canvas->Pixels[ix][iy]=c1;

apix[ix][iy][0]=0;

}

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::Image2MouseMove(TObject *Sender,

TShiftState Shift, int X, int Y)

{

ShowInfo(X,Y);

if (actLockView->Checked) return;

int ix=int(X/zoom),iy=int(Y/zoom);

oldselline=selline;

oldselnode=selnode;

selline=apix[ix][iy][1];

selnode=apix[ix][iy][2];

TPoint p=NodeCentre(selnode);

if(Shift.Contains(ssLeft))

{

if(apix[ix][iy][0]!=1)

{

apix[ix][iy][0]=1;

Image1->Canvas->Pen->Color=c0;

Image1->Canvas->Pixels[ix][iy]=c0;

}

else

Image1->Canvas->MoveTo(ix,iy);

}

else if(Shift.Contains(ssRight))

{

if(apix[ix][iy][0]!=0)

{

apix[ix][iy][0]=0;

Image1->Canvas->Pen->Color=c1;

Image1->Canvas->Pixels[ix][iy]=c1;

}

else

Image1->Canvas->MoveTo(ix,iy);

}

if(actLineLightCheck->Checked && selline!=oldselline)

{

if(apix[ix][iy][1]>0) // есть линия

{

DrawGrid();

Image2->Canvas->Pen->Color=c2;

for(int i=0;i<w;i++) // выделяем линию

{

for(int j=0;j<h;j++)

{

if(apix[i][j][1]==selline) // линия

{

Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));

Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));

Image2->Canvas->LineTo(int(zoom*i),int(zoom*j));

if(NeigCount(i,j)==1) // начало линии

{

Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));

Image2->Canvas->MoveTo(int(zoom*(i+1)),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));

}

if(apix[i][j][2]>0) // пересечение линии с узлом

{

Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));

p=NodeCentre(apix[i][j][2]);

Image2->Canvas->Pen->Color=c4;

Image2->Canvas->MoveTo(int(zoom*p.x),int(zoom*p.y));

Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*p.y));

Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*(p.y+1)));

Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*(p.y+1)));

Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*p.y));

Image2->Canvas->Pen->Color=c2;

}

}

} // for j

} // for i

}

} // actLineLightCheck->Checked

if(actSegLightCheck->Checked && selnode!=oldselnode)

{

if(apix[ix][iy][2]>0) // есть узел

{

DrawGrid();

Image2->Canvas->Pen->Color=c3;

for(int i=0;i<w;i++) // выделяем узел

{

for(int j=0;j<h;j++)

{

if(apix[i][j][2]==selnode) // узел

{

Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));

Image2->Canvas->LineTo(int(zoom*i),int(zoom*(j+1)));

Image2->Canvas->LineTo(int(zoom*i),int(zoom*j));

if(apix[i][j][1]>0) // пересечение узла с линией

{

Image2->Canvas->MoveTo(int(zoom*i),int(zoom*j));

Image2->Canvas->LineTo(int(zoom*(i+1)),int(zoom*(j+1)));

}

}

} // for j

} // for i

//

Image2->Canvas->Pen->Color=c4;

Image2->Canvas->MoveTo(int(zoom*p.x),int(zoom*p.y));

Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*p.y));

Image2->Canvas->LineTo(int(zoom*(p.x+1)),int(zoom*(p.y+1)));

Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*(p.y+1)));

Image2->Canvas->LineTo(int(zoom*p.x),int(zoom*p.y));

}

} // actSegLightCheck->Checked

}

//---------------------------------------------------------------------------

void TfrmLineSeg::ShowInfo(int X,int Y)

{

unsigned char r,g,b;

int ix=int(X/zoom),iy=int(Y/zoom);

if (X>=0 && Y>=0)

{

sb1->Panels->Items[1]->Text=IntToStr(ix);

sb1->Panels->Items[3]->Text=IntToStr(h-1-iy);

r=Image1->Canvas->Pixels[ix][iy];

g=Image1->Canvas->Pixels[ix][iy] >>8;

b=Image1->Canvas->Pixels[ix][iy] >>16;

sb1->Panels->Items[5]->Text=IntToStr(r);

sb1->Panels->Items[7]->Text=IntToStr(g);

sb1->Panels->Items[9]->Text=IntToStr(b);

}

sb1->Panels->Items[11]->Text=IntToStr(int(zoom));

// if(apix[ix][iy][0]!=-1)

{

sb1->Panels->Items[13]->Text=IntToStr(apix[ix][iy][0]);

sb1->Panels->Items[15]->Text=IntToStr(apix[ix][iy][1]);

}

sb1->Panels->Items[17]->Text=IntToStr(apix[ix][iy][2]);

sb1->Panels->Items[19]->Text=IntToStr(apix[ix][iy][3]);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoom1Execute(TObject *Sender)

{

zoom=1.0f;

Image1->Width=Image1->Picture->Width;

Image1->Height=Image1->Picture->Height;

DrawGrid();

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actAnalyzeExecute(TObject *Sender)

{

MemoLog->Clear();

actAnalyzeNodeExecute(Sender);

actAnalyzeSegExecute(Sender);

}

//---------------------------------------------------------------------------

int __fastcall TfrmLineSeg::NeigCount(int x, int y)

{

int n=0;

if(Image1->Canvas->Pixels[x-1][y-1]==c0 && x>0 && y>0) n+=1; // lu=1

if(Image1->Canvas->Pixels[x ][y-1]==c0   && y>0) n+=1; // u=2

if(Image1->Canvas->Pixels[x+1][y-1]==c0 && x<w && y>0) n+=1; // ru=3

if(Image1->Canvas->Pixels[x-1][y ]==c0 && x>0 ) n+=1; // l=4

if(Image1->Canvas->Pixels[x+1][y ]==c0 && x<w ) n+=1; // r=5

if(Image1->Canvas->Pixels[x-1][y+1]==c0 && x>0 && y<h) n+=1; // ld=6

if(Image1->Canvas->Pixels[x ][y+1]==c0   && y<h) n+=1; // d=7

if(Image1->Canvas->Pixels[x+1][y+1]==c0 && x<w && y<h) n+=1; // rd=8

return (n);

}

//---------------------------------------------------------------------------

int TfrmLineSeg::VectMove(int &x, int &y, int vect)

{

int res=0;

if(vect>0) wlog("VectMove: new point");

else if(vect<0 && vect>-10) wlog("VectMove: new node");

else if(vect<-10 && vect>-20) wlog("VectMove: existing node");

else wlog("VectMove: ERROR POINT");

int amvect=abs(vect) % 10;

switch(amvect)

{

// точка принадлежит линии

case 1: x-=1; y-=1; res=1; break;

case 2: y-=1;  res=1; break;

case 3: x+=1; y-=1; res=1; break;

case 4: x-=1;  res=1; break;

case 5: x+=1;  res=1; break;

case 6: x-=1; y+=1; res=1; break;

case 7: y+=1;  res=1; break;

case 8: x+=1; y+=1; res=1; break;

}

return res;

}

void __fastcall TfrmLineSeg::FormCanResize(TObject *Sender, int &NewWidth,

int &NewHeight, bool &Resize)

{

if(NewHeight<300) Resize=false;

}

//---------------------------------------------------------------------------

void TfrmLineSeg::ZoomTo(double z)

{

if(z<0.1) zoom=0.1f;

else if(z>maxzoom) zoom=maxzoom;

else zoom=z;

Image1->Width=int(Image1->Picture->Width*zoom);

Image1->Height=int(Image1->Picture->Height*zoom);

DrawGrid();

ShowInfo(-1,-1);

}

//---------------------------------------------------------------------------

AnsiString TfrmLineSeg::VectToStr(int v)

{

switch(v)

{

case 1:return ("LU");

case 2:return ("U");

case 3:return ("RU");

case 4:return ("L");

case 5:return ("R");

case 6:return ("LD");

case 7:return ("D");

case 8:return ("RD");

case -1:return ("LUn");

case -2:return ("Un");

case -3:return ("RUn");

case -4:return ("Ln");

case -5:return ("Rn");

case -6:return ("LDn");

case -7:return ("Dn");

case -8:return ("RDn");

default:return("");

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actNewFileExecute(TObject *Sender)

{

if(frmImgSize->ShowModal()==mrOk)

{

try

{

w=StrToInt(frmImgSize->edtWidth->Text);

h=StrToInt(frmImgSize->edtHeight->Text);

Image1->Picture->Bitmap->Width=w;

Image1->Picture->Bitmap->Height=h;

Image1->Width=w;

Image1->Height=h;

Image1->Canvas->FillRect(Image1->ClientRect);

zoom=1.0f;

scb1->Enabled=true;

for(int i=0;i<=w-1;i++) // maxw-1

for(int j=0;j<=h-1;j++) // maxh-1

{

apix[i][j][0]=Image1->Canvas->Pixels[i][j]==c0?1:0;

apix[i][j][1]=apix[i][j][2]=-1;

}

}

catch (...)

{

MessageBox(Handle,"Неверно указано число", "Ошибка", MB_OK);

}

DrawGrid();

ShowInfo(-1,-1);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actGridCheckExecute(TObject *Sender)

{

ValidateView();

DrawGrid();

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actLightCheckExecute(TObject *Sender)

{

ValidateView();

DrawGrid();

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoom10Execute(TObject *Sender)

{

ZoomTo(10.0f);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actLineLightCheckExecute(TObject *Sender)

{

ValidateView();

DrawGrid();

}

//---------------------------------------------------------------------------

void TfrmLineSeg::wlog(AnsiString s)

{

if(logs)

if(s!="")

MemoLog->Lines->Add(s);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSegLightCheckExecute(TObject *Sender)

{

ValidateView();

DrawGrid();

}

//---------------------------------------------------------------------------

void TfrmLineSeg::ValidateView()

{

Image2->Visible=actGridCheck->Checked

|| actLightCheck->Checked

|| actLineLightCheck->Checked

|| actSegLightCheck->Checked;

}

double TfrmLineSeg::plDistance(double x,double y,double x1,double y1,double x2,double y2)

{

double R=0.0f;

try

{

R=((y1-y2)*x+(x2-x1)*y+(x1*y2-x2*y1))/sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));

}

catch(...)

{ }

 return fabs(R);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actLockViewExecute(TObject *Sender)

{

ValidateView();

}

//---------------------------------------------------------------------------

AnsiString TfrmLineSeg::StrToLen(AnsiString str, int len)

{

AnsiString s=str;

while(s.Length()<len) s=" "+s;

return s;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::NeigNode(int x, int y, int n)

{

int i,j;

AnsiString s;

if(x<0 || y<0 || x>=w || y>=h) return; //если не принадлежит области изображения

if(apix[x][y][0]!=1) return; // если не является точкой

if(apix[x][y][2]!=-1) return; // если уже обработана на принадлежность узлу

if(NeigCount(x,y)<=2) return;// если мало соседей для сегментации

if(apix[x][y][2]==-1) // если точка не обработана

apix[x][y][2]=n; // точка будет принадлежать узлу n

// wlog(IntToStr(x)+","+IntToStr(y));

// обрабатываем ее соседей

NeigNode(x-1,y-1,n); NeigNode(x,y-1,n); NeigNode(x+1,y-1,n);

NeigNode(x-1,y,n);              NeigNode(x+1,y,n);

NeigNode(x-1,y+1,n); NeigNode(x,y+1,n); NeigNode(x+1,y+1,n);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actAnalyzeNodeExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск узлов...";

AnsiString s;

TPoint p;

int i,j,x,y,x1,y1,x2,y2,ssize,nsegs, v,oldv;

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][2]=-1;

i=0; j=0;

nsegs=0;

wlog("Поиск узлов...");

while(j<h)

{

while(i<w)

{

if(apix[i][j][0]==1 // есть точка

&& apix[i][j][2]==-1 // не обработана на принадлежность узлу

&& NeigCount(i,j)>2) // является частью узла

{// начинаем выделение узла

nsegs+=1;

wlog("Найден узел №"+IntToStr(nsegs));

// wlog("Точки в области узла:");

NeigNode(i,j,nsegs); // обрабатываем точки вокруг узла

p=NodeCentre(nsegs);

wlog("Координаты узла: "+IntToStr(p.x)+","+IntToStr(h-1-p.y));

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Поиск узлов завершен");

wlog("ВСЕГО УЗЛОВ: "+IntToStr(nsegs));

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::NeigLine(int x,int y, int n)

{

int nc=NeigCount(x,y);

if(nc==1 || nc==2) // если начало или продолжение линии

{

apix[x][y][1]=n;

wlog(IntToStr(x)+","+IntToStr(h-1-y));

// если (есть точка И не обработана на принадлежность линии)

if(apix[x-1][y-1][0]==1 && apix[x-1][y-1][1]==-1) NeigLine(x-1,y-1,n);

if(apix[x ][y-1][0]==1 && apix[x ][y-1][1]==-1) NeigLine(x,y-1,n);

if(apix[x+1][y-1][0]==1 && apix[x+1][y-1][1]==-1) NeigLine(x+1,y-1,n);

if(apix[x-1][y ][0]==1 && apix[x-1][y ][1]==-1) NeigLine(x-1,y,n);

if(apix[x+1][y ][0]==1 && apix[x+1][y ][1]==-1) NeigLine(x+1,y,n);

if(apix[x-1][y+1][0]==1 && apix[x-1][y+1][1]==-1) NeigLine(x-1,y+1,n);

if(apix[x ][y+1][0]==1 && apix[x ][y+1][1]==-1) NeigLine(x,y+1,n);

if(apix[x+1][y+1][0]==1 && apix[x+1][y+1][1]==-1) NeigLine(x+1,y+1,n);

}

else if(nc>2) // соединение с узлом

{

apix[x][y][1]=n;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actAnalyzeSegExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск сегментов линий...";

AnsiString s;

int i,j,x,y,x1,y1,x2,y2,llen,nlines, v,oldv;

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][1]=-1;

i=0; j=0;

nlines=0;

wlog("Поиск сегментов...");

while(j<h)

{

while(i<w)

{

if(apix[i][j][0]==1 // есть точка

&& apix[i][j][1]==-1 // и она не обработана на принадлежность сегменту линии

&& (NeigCount(i,j)==1 // и является началом (1 сосед)

|| NeigCount(i,j)==2)) // или продолжением линии (2 соседа)

{// начинаем выделение сегмента

nlines+=1;

wlog("Найден сегмент №"+IntToStr(nlines)+": ["+IntToStr(i)+","+IntToStr(h-1-j)+"]");

wlog("Точки сегмента:");

NeigLine(i,j,nlines); // обрабатываем сегмент линии

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Поиск сегментов завершен");

wlog("ВСЕГО СЕГМЕНТОВ: "+IntToStr(nlines));

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actMatchLinesExecute(TObject *Sender)

{

sb1->SimplePanel=true; sb1->SimpleText="Поиск линий...";

int i,j,cline,cseg,x,y;

double dist,mindist;

TPoint p;

wlog("Поиск линий...");

for(i=0;i<=w-1;i++) // maxw-1

for(j=0;j<=h-1;j++) // maxh-1

apix[i][j][3]=-1;

i=0; j=0;

while(j<h)

{

while(i<w)

{

if(apix[i][j][1]>0 && apix[i][j][2]>0 // есть соединение с сегментом

&& apix[i][j][3]==-1 // точка не обработана

)

{ // обрабатываем точку и выполняем поиск ей соответствующей

apix[i][j][3]=1;

cline=apix[i][j][1]; // текущая линия

cseg=apix[i][j][2]; // текущий сегмент

p=NodeCentre(cseg);

mindist=MAXDOUBLE;

x=y=-1;

wlog("Поиск соответствия фрагменту "+IntToStr(apix[i][j][1])+" ["+IntToStr(i)+","+IntToStr(j)+"]");

wlog("Центр сегмента "+IntToStr(cseg)+" ["+IntToStr(p.x)+","+IntToStr(p.y)+"]");

for(int j1=0;j1<h;j1++) // поиск точки соответствия

for(int i1=0;i1<w;i1++)

{

if(apix[i1][j1][0]==1 // есть точка

&& apix[i1][j1][3]==-1 // не обработана на соответствие линий

&& apix[i1][j1][1]>0 && apix[i1][j1][2]==cseg // является пересечением этого сегмента с одной из линий

)

{

if((dist=plDistance(p.x,p.y,i,j,i1,j1))<=mindist) // если образует наименьшее отклонение от центра сегмента

{ // запоминаем точку как самую подходящую

x=i1; y=j1;

mindist=dist;

wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - соотв.:"+FloatToStr(dist));

}

else

{

wlog("["+IntToStr(i1)+","+IntToStr(j1)+"] - не соотв:"+FloatToStr(dist));

}

}

}

if(x>0 && y>0)

{

wlog("Найдено соответствие фрагментов: "+IntToStr(cline)+" и "+IntToStr(apix[x][y][1]));

apix[x][y][3]=1; // точка обработана

FillLine(apix[x][y][1],cline); // заполняем линию

}

}

i+=1;

} // while i

i=0; j+=1;

} // while j

DrawGrid();

wlog("Line matching end");

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::FillLine(int n1, int n2)

{

for(int i=0;i<=w-1;i++) // maxw-1

for(int j=0;j<=h-1;j++) // maxh-1

if(apix[i][j][1]==n1) apix[i][j][1]=n2;

}

//---------------------------------------------------------------------------

TPoint TfrmLineSeg::NodeCentre(int n)

{

int i=0, j=0, cnt=0, xsum=0, ysum=0,x=0,y=0;

while(j<h)

{

while(i<w)

{

if(apix[i][j][2]==n // точка принадлежит этому узлу

// && apix[i][j][1]>0 // есть пересечение с линией

)

{

xsum+=i;

ysum+=j;

cnt+=1;

}

i+=1;

} // while i

i=0; j+=1;

} // while j

if(cnt>0)

{

x=xsum/cnt;

y=ysum/cnt;

}

return Point(x,y);

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actZoomWndExecute(TObject *Sender)

{

if(w>0 || h>0)

{

zoom=min(scb1->Width,scb1->Height)/max(w,h);

ZoomTo(zoom);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::GetLineVect(int x,int y,int n)

{

TPoint p;

if(apix[x][y][1]==n && apix[x][y][3]==-1) // принадлежит этой линии и не обработана в код

{

// обработка текущей точки

apix[x][y][3]=1;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

// обрабтка продолжения линии

if(apix[x][y][2]>0) // если пересечение с сегментом

{// обработка линии внутри сегмента

p=FindMatch(x,y);

CodeLine(x,y,p.x,p.y); // вывод кода линии внутри сегмента

x=p.x;

y=p.y;

apix[x][y][3]=1;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

}

GetLineVect(x-1,y-1,n); GetLineVect(x,y-1,n); GetLineVect(x+1,y-1,n);

GetLineVect(x-1,y,n); GetLineVect(x+1,y,n);

GetLineVect(x-1,y+1,n); GetLineVect(x,y+1,n); GetLineVect(x+1,y+1,n);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::CodeLine(int x1,int y1,int x2,int y2)

{

wlog("Кодирование линии ["+IntToStr(x1)+","+IntToStr(h-1-y1)+"]-["+IntToStr(x2)+","+IntToStr(h-1-y2)+"]:");

if(abs(x1-x2)>abs(y1-y2)) // точек по x больше

{

wlog("Цикл по оси x. Точки линии:");

int x, y, xa=min(x1,x2), xb=max(x1,x2);

double k=double(y2-y1)/(x2-x1), b=y1-x1*k;

x=xa+1;

while(x<xb)

{

y=k*x+b;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(h-1-y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

wlog(IntToStr(x)+","+IntToStr(h-1-y));

x+=1;

}

}

else // точек по y больше

{

wlog("Цикл по оси y. Точки линии:");

int x, y, ya=min(y1,y2), yb=max(y1,y2);

double k=double(x2-x1)/(y2-y1), b=x1-y1*k;

y=ya+1;

while(y<yb)

{

x=k*y+b;

if(linecode=="")

linecode+=IntToStr(x)+","+IntToStr(h-1-y);

else

linecode+=","+IntToStr(x)+","+IntToStr(h-1-y);

wlog(IntToStr(x)+","+IntToStr(h-1-y));

y+=1;

}

}

}

//---------------------------------------------------------------------------

TPoint __fastcall TfrmLineSeg::FindMatch(int x, int y)

{

int i,j;

TPoint p;

p.x=x;

p.y=y;

i=0; j=0;

while(j<h)

{

while(i<w)

{

if(apix[i][j][1]==apix[x][y][1] // если принадлежит той же линии

&& apix[i][j][2]==apix[x][y][2] // и принадлежит тому же сегменту

&& (i!=x || j!=y) // и это другая точка

)

{ // это искомая точка

p.x=i;

p.y=j;

}

i+=1;

} // while i

i=0; j+=1;

} // while j

return p;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actMatchOutExecute(TObject *Sender)

{

int i,j,lineno,lnum;

sb1->SimplePanel=true; sb1->SimpleText="Вывод кода линий...";

for(j=0;j<h;j++) // инициализация массива временных атрибутов

for(i=0;i<w;i++)

apix[i][j][3]=-1;

MemoOut->Clear();

lnum=0;

for(j=0;j<h;j++)

for(i=0;i<w;i++)

{

if(apix[i][j][1]>0// есть линия

&& apix[i][j][3]==-1 // и она не обработана

&& (NeigCount(i,j)==1 // точка является началом линии

|| apix[i][j][2]>0) // или узлом

)

{ // формируем код для этой линии

lineno=apix[i][j][1];

lnum+=1;

linecode="";

GetLineVect(i,j,lineno);

MemoOut->Lines->Add(IntToStr(lnum)+":"+linecode);

wlog(IntToStr(lnum)+"(line #"+IntToStr(lineno)+"):"+linecode);

}

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actOpenArrayExecute(TObject *Sender)

{

int i,j;

AnsiString s;

OpenDialog1->Title="Открыть массив точек";

OpenDialog1->Filter="Файлы массивов точек (*.dat)|*.dat|Все файлы (*.*)|*.*";

if(OpenDialog1->Execute())

{

sb1->SimplePanel=true; sb1->SimpleText="Открытие массива точек...";

mArray->Lines->LoadFromFile(OpenDialog1->FileName);

try

{

w=StrToInt(mArray->Lines->Strings[0]);

h=StrToInt(mArray->Lines->Strings[1]);

if(w>0 & h>0)

{

Image1->Picture->Bitmap->Width=w;

Image1->Picture->Bitmap->Height=h;

Image1->Width=w;

Image1->Height=h;

Image1->Canvas->FillRect(Image1->ClientRect);

scb1->Enabled=true;

ZoomTo(zoom);

for(j=0;j<h;j++)

{

s=mArray->Lines->Strings[j+2];

for(i=0;i<w;i++)

{

apix[i][j][1]=apix[i][j][2]=apix[i][j][3]=-1;

if(s[i+1]=='1') // есть точка

{

apix[i][j][0]=1;

Image1->Canvas->Pixels[i][j]=c0;

}

else // нет точки

{

apix[i][j][0]=0;

Image1->Canvas->Pixels[i][j]=c1;

}

}

}

}

else

throw Exception("");

}

catch (...)

{

MessageBox(Handle,"Ошибка открытия массива", "ОШИБКА", MB_OK);

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSaveArrayExecute(TObject *Sender)

{

int i,j;

AnsiString s;

SaveDialog1->Filter="Файлы массивов точек (*.dat)|*.dat|Все файлы (*.*)|*.*";

SaveDialog1->DefaultExt="*.dat";

SaveDialog1->Title="Сохранить массив точек";

if(SaveDialog1->Execute())

{

sb1->SimplePanel=true; sb1->SimpleText="Запись массива точек...";

mArray->Clear();

mArray->Lines->Add(IntToStr(w));

mArray->Lines->Add(IntToStr(h));

for(j=0;j<h;j++)

{

s="";

for(i=0;i<w;i++)

{

s+=apix[i][j][0]==1? '1': '0';

}

mArray->Lines->Add(s);

}

mArray->Lines->SaveToFile(SaveDialog1->FileName);

sb1->SimpleText=""; sb1->SimplePanel=false;

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actOptionsExecute(TObject *Sender)

{

frmOptions->Label1->Font->Color=c5;

frmOptions->Label2->Font->Color=c2;

frmOptions->Label3->Font->Color=c3;

frmOptions->Label4->Font=MemoLog->Font;

frmOptions->Label5->Font=MemoOut->Font;

frmOptions->cbLogs->Checked=logs;

if(frmOptions->ShowModal()==mrOk)

{

try

{

c5=frmOptions->Label1->Font->Color;

c2=frmOptions->Label2->Font->Color;

c3=frmOptions->Label3->Font->Color;

MemoLog->Font=frmOptions->Label4->Font;

MemoOut->Font=frmOptions->Label5->Font;

logs=frmOptions->cbLogs->Checked;

}

catch (...)

{

MessageBox(Handle,"Неверно указано число", "Ошибка", MB_OK);

}

DrawGrid();

ShowInfo(-1,-1);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSaveCodeExecute(TObject *Sender)

{

SaveDialog1->Filter="Файлы кодов линий (*.lsc)|*.lsc|Все файлы (*.*)|*.*";

SaveDialog1->DefaultExt="*.lsc";

SaveDialog1->Title="Сохранить коды линий";

if(SaveDialog1->Execute())

{

MemoOut->Lines->SaveToFile(SaveDialog1->FileName);

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::GetLineVect2(int x,int y,int n)

{

TPoint p;

if(apix[x][y][1]==n && apix[x][y][3]==-1) // принадлежит этой линии и не обработана в код

{

// обработка текущей точки

if (NeigCount(x,y)==1) // если конец линии

{ // обработка конца линии

if(nodescnt==0) // если не было найдено конечных точек

{

nodescnt+=1;

xs1=x; ys1=1; // первая координата

}

else if(nodescnt==1) // если уже имеется одна конечная точка

{

}

apix[x][y][3]=1;

xs1=x;

ys1=y;

nodescnt+=1;

}

else if(apix[x][y][2]>0) // если начинается узел

{

}

else // продолжение линии, продолжаем обработку

{

GetLineVect(x-1,y-1,n); GetLineVect(x,y-1,n); GetLineVect(x+1,y-1,n);

GetLineVect(x-1,y,n); GetLineVect(x+1,y,n);

GetLineVect(x-1,y+1,n); GetLineVect(x,y+1,n); GetLineVect(x+1,y+1,n);

}

}

}

//---------------------------------------------------------------------------

void __fastcall TfrmLineSeg::actSegCodeOutExecute(TObject *Sender)

{

int i,j,lineno,lnum;

sb1->SimplePanel=true; sb1->SimpleText="Вывод кода сегментов...";

for(j=0;j<h;j++) // инициализация массива временных атрибутов

for(i=0;i<w;i++)

apix[i][j][3]=-1;

MemoOut->Clear();

lnum=0;

for(j=0;j<h;j++)

for(i=0;i<w;i++)

{

if(apix[i][j][1]>0 // есть сегмент

&& apix[i][j][3]==-1 // и он не обработан

&& (NeigCount(i,j)==1 // точка является началом сегмента

|| NeigCount(i,j)==2) // или продолжением сегмента

)

{ // формируем код для этой линии

xs1=ys1=xs2=ys2=xs3=ys3=-1;

nodescnt=0;

lineno=apix[i][j][1];

lnum+=1;

linecode="";

GetLineVect2(i,j,lineno);

MemoOut->Lines->Add(IntToStr(lnum)+":"+linecode);

wlog(IntToStr(lnum)+"(line #"+IntToStr(lineno)+"):"+linecode);

}

}

sb1->SimpleText=""; sb1->SimplePanel=false;

}

//---------------------------------------------------------------------------

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: