//---------------------------------------------------------------------------
#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;
}
//---------------------------------------------------------------------------