//Обработка картинки, ее изменение
//Обработка линии на которую указывает imap
//Исправление псевдо-раздвоений и псевдо-окончаний на указанной линии
{
int changeN = 0; //количество модификаций на линии
int kol = 0; //количество пройденных точек
int vec = 0; //направление поиска очередной точки
int tekS = 0; //Текущее количество коротких векторов
CPoint A, //Начало вектора
B; //Конец вектора
TAbsFing vecDotS; //массив точек для коротких векторов
TAbsFing vecDotL; //массив точек для длинных векторов
TAbsFing historyDotL; //история точек для длинных векторов
TAbsDot _tmpDotFing;
TAbsFing::iterator iter;
TAbsDot resetDot, bestDot;
double alpha; //направление вектора (в радианах)
int stopKol = 1500; //предел шагов
int ret = 0; //счетчик шагов после прохождения начальной точки
bool homeOver = false; //признак окончания обработки
_dot->pr1 = false;
A = _dot->coord; B = _dot->coord;
CPoint olddot, dot = _dot->coord; //Текущая точка на линии
do{
//основной цикл обработки,
//варианты завершения цикла
//продолжается до тех пор пока вся линия не будет пройдена (нормальный вариант)
//зацикливание (не нормальный вариант, их несколько)
//
olddot = dot;
dot = pic->NextDotCW(dot, vec); //Поиск следующей точки _по часовой_ стрелке
if(dot.x == olddot.x && dot.y == olddot.y)
{//положение точки не изменилось => выход//
CString s;
s.Format("x = %d, y = %d, kol= %d", dot.x, dot.y, kol);
if(MESSAGEOUT)MessageBox(0, "положение точки не изменилось => выход\n" + s, "", MB_OK);
return changeN;
}
kol++; //подсчет пройденных точек
if(kol % LEN_S == 0)
{//появился новый короткий вектор
tekS++;
A = B;
B = dot;
//pic2->Line(A,B, 1, 0x999999);
_tmpDotFing.coord = A;
alpha = GetAlpha(A, B); //расчет локального направления между KOL_S пикселями (направление короткого вектора)//
double dAlpha = 0.0; //Разница углов
if(vecDotS.size() > 0) //в списке можно взять предыдущее значение
dAlpha = alpha - vecDotS.begin()->alpha;
/**/ if (abs(dAlpha) >= M_PI) //разница между новым углом и предыдущим не нормальная!
{//необходимо скорректировать текущую alpha
/**/ if (dAlpha < 0.0)
while (abs(dAlpha) > M_PI)
alpha += 2.0 * M_PI;
dAlpha += 2.0 * M_PI;
}else
while (dAlpha >= M_PI)
alpha -= 2.0 * M_PI;
dAlpha -= 2.0 * M_PI;
_tmpDotFing.alpha = alpha; //запоминание направления из точки А//
vecDotS.push_front(_tmpDotFing);
///////////////////////////////////////////////////////////////////////
///////проверяем два соседних длинных вектора при условии что//////////
///////пройдено достаточно точек, чтоб сравнивать длнинные вектора/////
if(vecDotS.size() < KOL_S) continue;
//Вычисление среднего направления LEN_L коротких векторов//
//запись данных по длинному вектору////////////////////////
double sumAlpha = 0.0;
iter = vecDotS.begin();
vecDotL.clear(); //пересчитаем длинные вектора
for(int i = 0; i < KOL_S; i++)
sumAlpha += iter->alpha;
if ((i+1) % LEN_L == 0)
_tmpDotFing = *iter;
_tmpDotFing.alpha = sumAlpha / LEN_L;
vecDotL.push_back(_tmpDotFing);
sumAlpha = 0.0;
iter++;
if (abs(vecDotL.begin()->alpha) > 3*2*M_PI)
{//слишком много оборотов//
s.Format("alpha = %.2f", vecDotL.begin()->alpha*180);
if(MESSAGEOUT)MessageBox(0, "слишком много оборотов\n"+s, "", MB_OK);
//проверяем два соседних длинных вектора//
dAlpha = vecDotL.begin()->alpha - (++vecDotL.begin())->alpha;
if (abs(dAlpha) > (TEST_ALPHA / 180.0 * M_PI)) //сильный изгиб//
if (historyDotL.empty())
{ //сохранение состояния//
resetDot = vecDotL.back();
bestDot.alpha = 0.0;
if (dAlpha > 0) //раздвоение
alpha = (vecDotL.front().alpha - M_PI + (vecDotL.back().alpha)) / 2.0;
else //окончание
alpha = (vecDotL.front().alpha + M_PI + (vecDotL.back().alpha)) / 2.0;
_tmpDotFing = vecDotL.front();
_tmpDotFing.alpha = alpha; //направление в СТ (специфичная точка)//
_tmpDotFing.type = dAlpha<0; //тип СТ//
historyDotL.push_front(_tmpDotFing);
if(bestDot.alpha <= abs(dAlpha))
bestDot.coord = _tmpDotFing.coord;
bestDot.alpha = abs(dAlpha);
else //сильный изгиб//
if (!historyDotL.empty()) //был _пройден_ сильный изгиб
alpha = 0.0;
for(iter = historyDotL.begin(); iter != historyDotL.end(); iter++)
alpha += iter->alpha;
alpha /= historyDotL.size(); //среднее значение в пройденной СТ
iter = historyDotL.begin();
for(unsigned int i = 0; i<(historyDotL.size()/2); i++) iter++;
CPoint wdot = bestDot.coord; //наиболее вероятная точка для СТ
CPoint dotForAccept = FindAcceptDot(wdot, alpha, iter->type);
if (dotForAccept.x != -1)
{ //точка имеет продолжение//
COLORREF cl;
cl = (historyDotL.begin()->type)?0x000000:0xffffff;
//здесь можно поиграть с разной толщиной линии//
pic->Line(wdot, dotForAccept, 4, cl);
_dot->pr1 = true; //эту линию необходио еще раз проанализировать
changeN++;
stopKol += (stopKol-kol < 200)?200:0;
//stopKol += (kol*1.5 > stopKol)?500:0;
//загрузить начальное состояние
if(!historyDotL.begin()->type)
{ //если ликвидировано слипание то необходимо добавить новую точку на карту
_map.push_back(TMapElDot(dot));
//пройдена начальная точка, продлим анализ
//очень возможно, что начальную точку мы больше не попадем
if(ret-KOL_S*LEN_S < 0)
ret = 0;
homeOver = false;
stopKol = 500;
A = B = dot = resetDot.coord;
vecDotS.clear();
vecDotL.clear();
//------------------------------
historyDotL.clear();
if (dot.x == _dot->coord.x && dot.y == _dot->coord.y)
{//вероятно обход линии завершен
if (kol <= 2)
{//Линия подозрительно короткая
s.Format("%d", kol);
if(MESSAGEOUT)MessageBox(0, "kol<=2 kol = " + s, "", MB_OK);
homeOver = true; //пройти необходимо дальше начала
stopKol = kol + KOL_L*LEN_L*LEN_S;
if (homeOver) ret++;
}while(ret < (LEN_L*LEN_S*KOL_L) && ret < stopKol && kol <= stopKol);
_dot->pr2 = false;
inline double TAnalysePicture::GetAlpha(const CPoint A, const CPoint B)
//Направлени из точки А в В [-pi,pi)
if(A == B) return 0.0;
double alpha;
if (A.x - B.x == 0)
if (A.y > B.y) alpha = M_PI_2;
else alpha = -M_PI_2;
double a = ((double)A.y-B.y)/((double)B.x-A.x);
alpha = atan(a);
if (A.x > B.x)
if (alpha < 0) alpha += M_PI;
else alpha -= M_PI;
if (A.y == B.y) alpha = -M_PI;
return alpha;
bool TAnalysePicture::TestFindDot(int _x, int _y)
//тест точки: Разность направлений вперед и назад должно быть меньше 110 градусов
const int len = 7;
CPoint A(_x, _y), B, C;
//первый вектор
B = A;
int vec = 0;
for(int i = 1; i<=len; i++)
B = tmpPic->NextDotCW(B, vec);
//------расчет угла-------//
double alpha1 = GetAlpha(A, B);
//второй вектор
C = B;
vec = 0;
B = tmpPic->NextDotCCW(B, vec);
if(abs(B.x-C.x) < 3 && abs(B.y-C.y) < 3) return true;
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30