//---------------------------------------------------------------------------
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);
}
elseif(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(intj1=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)
{
TPointp;
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;