Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Заливка области  (Прочитано 18038 раз)
0 Пользователей и 1 Гость смотрят эту тему.
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 25-10-2004 14:54 » 

Программа должна заполнять заданную область, например квадрат (должна то она больше, но пока и это не делает Жаль ).
Результат ее работы-это нарисованная прямая от правой грани до левой и все. Знаю что ошибся, но не вижу где, помогите найти ошибку,
вот код:
Код:
//////////================Sortirovka Massiva==================================/////////////////
////////////////////////////////////////////////////////////////////////////
int sortmass (int j,int schet, int **mass)
{
if(schet==0)
{mass[0][0]=NULL;mass[1][0]=NULL;}
else
{ for (int i=j; i<schet;i++)
{mass[0][i]=mass[0][i+1];
mass[1][i]=mass[1][i+1];}

 mass[0][schet]=NULL;
 mass[1][schet]=NULL;
 --schet;}
 
return schet;
}

///////////////////////////////////////////////////////////////////////////
////////=========================////////////////


////////////==================Proverka Massiva========================//////////////
///////////////////////////////////////////////////////////////////////////////////
     void proverk_mass(int **mass, int schet,COLORREF nov, CDC *hdc)
{

      for(int i=0; i<=schet; i++)
  {
               if(hdc->GetPixel(mass[0][i],mass[1][i])==nov)
schet=sortmass(i,schet,mass);
  }

}

////////////////////////////////////////////////////////////
//=========================///////////////



//====================//////////////////
/////////////////////////////////////////////////////////////////////////////
void zapoln(CPoint point, COLORREF old, COLORREF nov,COLORREF gran, CDC *hdc)
{

// COLORREF col;

unsigned long x=point.x, y=point.y;//, xl, yl, xr, yr;
unsigned long xrn=0, xln=0, xrv=0, xlv=0, xl=0, xr=0,xrrez=0;
int schet=0, kolvo=0, flag=0, fl=0;
    int **mass;
 mass=new int *[1];
 mass[0]=new int [50];
 mass[1]=new int [50];
 mass[0][0]=NULL; mass[1][0]=NULL;
//////////////////////////////////1begin/////////////////////////////////////////
                    
 
 for( ;hdc->GetPixel(x,y)==old;x++)
{; }
        
 
 xr=x;
             schet=0;
                   mass[0][schet]=x; mass[1][schet]=y;
  //schet++;
//x=mass[0][schet] ; y=mass[1][schet];
/////////////////////////////////////////1end/////////////////////////////////////////


//////////////Obschiy Cycl//////////////////
  for(;mass[0][0]!=NULL && mass[1][0]!=NULL;)
  {
      flag=0; fl=0;
  x=mass[0][0]; y=mass[1][0];

///////////////Kraynie Tochki//////////////////////
xr=xrrez=x;  
////////////////

if(hdc->GetPixel(xr-1,y+1)!=gran)
{ if (hdc->GetPixel(xr,y+1)==old && hdc->GetPixel(xr,y+1)==nov) //VTORE USLOVIE ==nov NENADO???
          {xrv=xr;//?????????
          //Zapis v mass i uvelichenie schetchika
          mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;
          }
else
{if(hdc->GetPixel(xr-1,y+1)==old && hdc->GetPixel(xr-1,y+1)==nov) //VTORE USLOVIE ==nov NENADO???
         {xrv=--xr;
         //Zapis v mass i uvelichenie schetchika
         mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;}
}}
else
  {for(;hdc->GetPixel(xr,y+1)==old && hdc->GetPixel(xr,y+1)==nov;) //VTORE USLOVIE ==nov NENADO???
  {xrv=xr;
  ++xr;}
  ///////////////////////////////
  //Zapis elementov v mass
//--xrv;  
mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;
}

////////////=====================================//////////////////

//KRAYNAYA TOCHKA VNIZU SPRAVA

xr=xrrez=x;
if (hdc->GetPixel(xrrez-1,y-1)!=gran)

{if(hdc->GetPixel(xrrez,y-1)==old&&hdc->GetPixel(xrrez,y-1)==nov) //VTORE USLOVIE ==nov NENADO???
           {xrn=xrrez;//???????????
           //Zapis v massiv
           mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;
           }
else
{if(hdc->GetPixel(xrrez-1,y-1)==old)
            {xrn=--xrrez;
            //Zapis v massiv i uvel schetchika
            mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;}
}}
else
   {for (;hdc->GetPixel(xrrez,y-1)==old;)
   {xrn=xrrez;
   ++xrrez;}
   ///////////////////////////
   ///Zapis elementov v mass
//--xrn;  
mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;
}

////=======================////////////////////////






/////////////////////////////////////2begin///////////////

 for(;hdc->GetPixel(x-1,y)==old;)
{
Sleep(100);
--x;
hdc->SetPixel(x,y,nov);



/////////////////////

}


//////////////////////////////2end/////////////////////////////////

//////////////////////////////3begin//////////////////////////////
proverk_mass(mass,schet,nov,hdc);
///////////////////////////////3End///////////////////////////////


///////////////////////////////////
}

/////////////////////////////////


//delete []mass;
//////////////////////////////////////////////////////////////////
}
« Последнее редактирование: 02-12-2007 15:43 от Алексей1153++ » Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #1 : 25-10-2004 17:38 » 

ой, ЁЁЁЁЁЁЁЁЁЁ... вот так и не въеду с перепугу да после работы ... Улыбаюсь

щас попробую разобраться, а пока посмотри это - я из готового проектика своего привожу (может поможет):

Код:
#define Height 20
#define Width 20
COLORREF  Pict[Height][Width];
#define StackSize_Fill  Height*Width*2 //размер стека заливки
int Stack_Fill[StackSize_Fill]; //стек заливки
int SP_Fill; //количество элементов в стеке заливки

Код:
//заливка замкнутой области в массиве
//COLORREF  Pict[Height][Width]
void fill(int x, int y, DWORD NewColor)
{
   COLORREF OldColor;
   OldColor = Pict[y][x];
   //OldColor - старый цвет пиксела затравки (то есть старый цвет)
   //NewColor - новый цвет
   //если старый цвет совпал с новым - возврат
   if(NewColor==OldColor) return;
   //очистка стека заливки
   SP_Fill=0;//количество элементов в стеке
   //помещение координат затравки в стек
   Push(x,y);
   //закраска области (с цветом OldColor) цветом NewColor
   while(SP_Fill)
   {
      //извлечь координаты из стека
      Pop(x,y);
      Pict[y][x]=NewColor; //закрасить пиксел новым цветом
      //поиск пикселов с цветом OldColor рядом с текущим пикселом
      if(x>0 && Pict[y][x-1]==OldColor )Push(x-1,y);//слева
      if(x<(Width-1) && Pict[y][x+1]==OldColor )Push(x+1,y); //справа
      if(y>0 && Pict[y-1][x]==OldColor )Push(x,y-1);//сверху
      if(y<(Height-1) && Pict[y+1][x]==OldColor )Push(x,y+1);//снизу
   }
//КАНЭЦ
}

Код:
//поместить координаты пиксела в стек заливки
void Push(int x, int y)
{
   if(SP_Fill==StackSize_Fill)
   {AfxMessageBox("ошибка: стек заливки полон");}
   else
   {
      Stack_Fill[SP_Fill++]=x;
      Stack_Fill[SP_Fill++]=y;
   }
}
Код:
//извлечь координаты пиксела из стека заливки
void Pop(int &x, int &y)
{
   if(SP_Fill==0)
   {AfxMessageBox("ошибка: стек заливки пуст");}
   else
   {
      y=Stack_Fill[--SP_Fill];
      x=Stack_Fill[--SP_Fill];
   }
}
тут размер стека заливки сделан равным двойному количеству элементов картинки Pict, поэтому вылетов за границы не будет. Но а-фэ-иксы с предупреждения всё же нужно – а вдруг Ага
« Последнее редактирование: 02-12-2007 15:47 от Алексей1153++ » Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 26-10-2004 18:43 » 

Я нашел пару ошибок:
Во-первых, моя старая беда, я перепутал "и" и "или". Там где ищутся крайние точки в условиях вместо && должно стоять ||.
 Теперь проблема в том, что не вызывается по неизвестным мне причинам функция sortmass.
 Надеюсь что кто-то сможет найти мою ошибку, мне важно чтобы заработала именно моя прога. Спасибо Алексей1153 за свой код, но моя цель исправить мой, я считаю, что в нем не так уж всё запущено Улыбаюсь.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #3 : 26-10-2004 19:58 » 

nikedeforest, я не навязываю - просто алгоритм предлагаю Улыбаюсь

тебя, кстати, бардак в коде твоём не смущает? Ага
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #4 : 26-10-2004 20:12 » 

хорошо, вот сейчас спать не буду, а приведу в порядок - тогда и ошибку приятно искать будет Ага

но если завтра просплю на работы - ты будешь виноват   Вот такой я вот
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #5 : 26-10-2004 21:07 » 


поначалу в глаза бросается вот что:
Код:
   mass=new int *[1];//создаём массив указателей на int из ОДНОГО элемента
    mass[0]=new int [50]; //и создаём для этого указателя массив
    mass[1]=new int [50]; //а это косяк!!! указателя mass[1] не существует

имхо надо
mass=new int *[2];

и ещё - не используй тут NULL, а лучше 0

короче надо дальше разбираться... Улыбаюсь
« Последнее редактирование: 02-12-2007 15:50 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #6 : 26-10-2004 21:19 » 

и ещё - твой стек mass расчитан всего на 50 координат, а их может и больше быть. Лучше завести переменную, хранящую размер, и если нужно будет сохранить 51-ю координату - размер массива надо увеличить в два раза и работать дальше. И т.д.

Нет, на сегодня меня не хватит - засыпаю.

Завтра продолжим вечером
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 26-10-2004 22:30 » 

Ну то что мой код надо упорядочивать Улыбаюсь это точно, каряво, не первый раз слышу, но как могу, наверное бардак в голове и на бумаге (в нашем случае на мониторе) бардак.

А теперь к делу:
    1)насчет массива **mass, там все в порядке, я проверял, через messagebox выводил, поэтому массив работает.
   2) насчет 50 элементов, это я согласен, но я пока не берусь за это, потому что смысла нет, пока прога не работает для маленького участка, а потом это все уладится, я думаю динамически выделять память и забирать ее также, но это уже как получится не будем загадывать.

 Так и приятная новость, я более менее локализовал ошибку и она находится в том месте , где ищутся крайние точки (отмечены как "Krainie tochki" и "KRAYNAYA TOCHKA VNIZU SPRAVA"). В связи с этим функция proverk_mass не вызывает функцию sortmass.
  Я попытался от этого избавиться таким образом:
    Функции sortmass и proverk_mass убираются , а код из sortmass вставляется в функцию zapoln туда где вызывалас proverk_mass

(код такой:  
Код:
if(schet==0)
{mass[0][0]=NULL;mass[1][0]=NULL;}
else
  for(int i=0; i<schet;i++)
{mass[0][i]=mass[0][i+1];
mass[1][i]=mass[1][i+1];}
mass[0][schet]=NULL;
mass[1][schet]=NULL;
schet--;
)
Сегодняшний успех таков, что прога заполняет квадрат, но на других объектах ведет себя некорректно:
1 Поиск правых крайних точек происходит неверно
2 Происходит , с течением времени, выход за границы.  

 Сейчас постараюсь как-нибудь представить код по лучше, хотя у меня врят ли это получится:

Код:
void zapoln(CPoint point, COLORREF old, COLORREF nov,COLORREF gran, CDC *hdc)
{

unsigned long x=point.x, y=point.y;//, xl, yl, xr, yr;
unsigned long xrn=0, xln=0, xrv=0, xlv=0, xl=0, xr=0,xrrez=0;
int schet=0, kolvo=0, flag=0, fl=0;
        unsigned long **mass;
 
 mass=new unsigned long *[1];
 mass[0]=new unsigned long [50];
 mass[1]=new unsigned long [50];
 mass[0][0]=NULL; mass[1][0]=NULL;
////////////////////////////////////////1begin////////
 for( ;hdc->GetPixel(x,y)==old;x++)
{; }
         --x;
 xr=x;
          schet=0;
          mass[0][schet]=x; mass[1][schet]=y;
          schet++;




////////////////////////////1end///////////////

                                  //////////////Obschiy Cycl//////////////////
  for(;mass[0][0]!=NULL || mass[1][0]!=NULL;)
  {
              flag=0; fl=0;
  x=mass[0][0]; y=mass[1][0];

///////////////Kraynie Tochki//////////////////////
xr=xrrez=x;  
////////////////

if(hdc->GetPixel(xr-1,y+1)!=gran)
{ if (hdc->GetPixel(xr,y+1)==old || hdc->GetPixel(xr,y+1)==nov)
          {xrv=xr;
        mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;
          }
else
{if(hdc->GetPixel(xr-1,y+1)==old || hdc->GetPixel(xr-1,y+1)==nov)
         {xrv=--xr;
         //Zapis v mass i uvelichenie schetchika
        mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;}}
}


else
  {for(;hdc->GetPixel(xr,y+1)==old || hdc->GetPixel(xr,y+1)==nov;)
  {xrv=xr;
  ++xr;}
    //Zapis elementov v mass              
mass[0][schet]=xrv; mass[1][schet]=y+1; schet++;
  }

////////////=====================================//////

//KRAYNAYA TOCHKA VNIZU SPRAVA

xr=xrrez=x;

if (hdc->GetPixel(xrrez-1,y-1)!=gran)

{if(hdc->GetPixel(xrrez,y-1)==old||hdc->GetPixel(xrrez,y-1)==nov)
           {xrn=xrrez;
           //Zapis v massiv

mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;
           }
else
{if(hdc->GetPixel(xrrez-1,y-1)==old||hdc->GetPixel(xrrez-1,y-1)==nov)
            {xrn=--xrrez;
mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;}
}}
else
   {for (;hdc->GetPixel(xrrez,y-1)==old|| hdc->GetPixel(xrrez,y-1)==nov;)
   {xrn=xrrez;
   ++xrrez;}
  
   ///Zapis elementov v mass
mass[0][schet]=xrn; mass[1][schet]=y-1; schet++;
}


/////////////////////////////////////2begin///////////////

 for(;hdc->GetPixel(x-1,y)==old;)
{

hdc->SetPixel(x,y,nov);
--x;
}

//////////////////////////////2end//////////////////////////

//////////////////////////////3begin//////////////////////

  if(schet==0)
{mass[0][0]=NULL;mass[1][0]=NULL;}
else
 for(int i=0; i<schet;i++)

{mass[0][i]=mass[0][i+1];
mass[1][i]=mass[1][i+1];}
mass[0][schet]=NULL;
mass[1][schet]=NULL;
schet--;

}
///////////////////////////////3End/////////////////////
delete []mass;
}
Квабрат заливается нормальна за искл бага по поводу того, что не закрашивает один пиксель в каждой линии, прямо чуточку не доходит до левой сотроны.

ВСЕ! Я очеь старался, но наверное все равно бардак.
А как делать выделение в форуме (здесь) для кода, может тогда по нормальней будет.

Хотелось бы добавить, что это первый этап написание этой проги, дело в том, что задание таково, что нужно, чтобы заливалась любая область с любыми помехами внутри, но насчет помех это потом, пока хоть область чтобы любую без помех заполняла.
  зы.
"хорошо, вот сейчас спать не буду, а приведу в порядок - тогда и ошибку приятно искать будет  
но если завтра просплю на работы - ты будешь виноват" - работа это святое, я и так очень благодарен за уделенное мне время.
  Еще раз спасибо и доброй ночи!!!
« Последнее редактирование: 02-12-2007 15:51 от Алексей1153++ » Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #8 : 27-10-2004 03:02 » 

nikedeforest, я вроде не проспал Улыбаюсь

тут ещё по поводу твоего нового поста:

:arrow:
Цитата
unsigned long **mass;
mass=new unsigned long *[1];
mass[0]=new unsigned long [50];
mass[1]=new unsigned long [50];

говоришь - проверял, в боксы печатал, но опять же:
mass=new unsigned long *[1];

 - ты создаёшь массив:
unsigned long* mass[1]   !!!!!!

какое в скобках число, столько и элементов!

0 - ноль элементов
1 - один элемент
2 - два элемента !!!

ты может путаешь с обращением к элементу массива, там НОМЕР элемента, он начинается с нуля, а тут -КОЛИЧЕСТВО  

короче - сделай mass=new unsigned long *[2]; , иначе ты портишь память, а там - такие глюки могут начаться, что  Я шокирован!

 :arrow:
Цитата
void zapoln(CPoint point, COLORREF old, COLORREF nov,COLORREF gran, CDC *hdc)

нафига тебе gran ? это маразм - максимальные границы описывать граничным цветом, юзер настройки винды поменял - и полетели! Нужно прямоугольной областью ограничивать - хотябы тем CDC, в котором рисуешь.

 :arrow:
Цитата
Хотелось бы добавить, что это первый этап написание этой проги, дело в том, что задание таково, что нужно, чтобы заливалась любая область с любыми помехами внутри, но насчет помех это потом, пока хоть область чтобы любую без помех заполняла.
зы.
помехи - это цвет Улыбаюсь . Ты лучше алгоритм приведи, хотя бы на словах. Потому что когда-то я тоже пытался делать что-то вроде твоего, но остановился на том, что во втором посте.
Просто в твоём случае - когда ведёшь линию вправо, с стек нужно помещать "завихрения", то есть пикселы старого цвета, которые остались сверху и снизу от линии сразу справа от встреченной помехи. Затем "завихрения" извлекаются из стека - и используются как новые затравки

Вот, например мой алгоритм во втором посте более прост, но там в стек могут попасть одинаковые координаты. В этом ничего страшного, просто один и тот же пиксел по нескольку раз проверяется на закраску, но не закрашивается заново, так как он уже к тому времени окрашен в нужный цвет.

 :arrow:
Цитата
А как делать выделение в форуме (здесь) для кода, может тогда по нормальней будет.
нажми серенькую кнопку "ответить" внизу страницы - там все теги показаны
 
код заключаешь в теги

[code]
тут коддддд
[/code]


 :arrow:

Цитата
ВСЕ! Я очеь старался, но наверное все равно бардак

тут я не помогу... Вырабатывай стиль - и придерживайся его

вот например у меня - если идёт блок {} , то в нём отступ на табуляцию:
Код:
for(;;)
{
   //код1
   if
   {
      //код2
   }
}

- вид уже улучшится сам по себе, и парные скобки легче находить
« Последнее редактирование: 02-12-2007 15:56 от Алексей1153++ » Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 27-10-2004 15:57 » 

"я вроде не проспал"- это хорошо Улыбаюсь, я же наоборот проспал, но все равно в институт успел Улыбаюсь.
"короче - сделай mass=new unsigned long *[2]; , иначе ты портишь память, а там - такие глюки могут начаться, что ..."-
но я проверял в массиве все нормально это 100%,  как я писал ранее крайние правые точки ищутся неверно.

"нафига тебе gran ? это маразм - максимальные границы описывать граничным цветом, юзер настройки винды поменял - и полетели! Нужно прямоугольной областью ограничивать - хотябы тем CDC, в котором рисуешь."-этого я не понял, особенно "хотя бы тем CDC в котором рисуешь", если можно поподробнее.
"когда ведёшь линию вправо, с стек нужно помещать "завихрения", то есть пикселы старого цвета, которые остались сверху и снизу от линии сразу справа от встреченной помехи. Затем "завихрения" извлекаются из стека - и используются как новые затравки"- почти согласен, но новые точки должны браться слева от помехи, а так все верно. Я в принципе представляю как буду это делать, просто пока надо, чтобы работала прога без глюков в обычной области.

Я бы хотел акцентировать внимание на поиске крайних правых точек, т.к. считаю, что там кроется ошибка и Я объясню почему:
 при работе проги квадрат заполняется нормально, а вот если заменить квадрат на область к примеру треугольник ну и пусть равнобедренный. Так вот заполняться он будет так:
Нарисуется линия от правого края до левого, затем все что сверху будет заполняться нормально, а вот то что снизу нет. Снизу получится как бы залитый квадрат, т.е. от места первоначальной затравки и вниз правая сторона треугольника удаляется, а вот линии рисуются не от края  стороны, а от значения Х крайней правой точки там где рисовалась первая полоса.
 Надеюсь нормально объяснил.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #10 : 27-10-2004 19:01 » 

Цитата
"короче - сделай mass=new unsigned long *[2]; , иначе ты портишь память, а там - такие глюки могут начаться, что ..."-
но я проверял в массиве все нормально это 100%, как я писал ранее крайние правые точки ищутся неверно.

слюшай, работать-то оно работает, по чистой случайности, но это как по чистой случайности начать собирать яблоки на участке злого соседа Улыбаюсь

если ты говоришь операционной системе:  mass=new unsigned long *[1], то ты только этот указатель можешь использовать без риска испортить память. Потому как на месте ((long*)mass)+1 будут расположены другие данные. А ты - хоба! - стёр их и поместил на их место адрес массива на 50 элементов. короче - это точно надо, что бы ты там не проверял, потому что это НЕКОРРЕКТНО.

Цитата
Нужно прямоугольной областью ограничивать - хотябы тем CDC, в котором рисуешь."-этого я не понял, особенно "хотя бы тем CDC в котором рисуешь", если можно поподробнее.

класс CDC - это класс контекста устройства. У тебя есть переменная CDC *hdc , которая есть указатель на экземпляр класса CDC. Контекст устройства - вещь прямоугольная. Ты можешь найти размеры её:

CRect rect;
int xmax,ymax;
рdc->GetClipBox(rect);
xmax=rect.Width();
ymax=rect.Height();

теперь ты знаешь, что у тебя должно быть
0 <= X <= xmax,
0 <= Y <= ymax,

и соответственно везде, где ты увеличиваешь или уменьшаешь координату - тебе надо следить, чтобы она не вылезла за границы.

но если известен ограничивающий прямоугольник меньший , чем весь размер контекста - бери этот прямоугольник

Цитата
почти согласен, но новые точки должны браться слева от помехи, а так все верно. Я в принципе представляю как буду это делать, просто пока надо, чтобы работала прога без глюков в обычной области

делать это я думаю так (но, опять повторяю - "энергоёмко", хотя... кстати насчёт этого - когда победим твою прогу, реализуй мой алгоритм в твоём формате тоже - и сравним быстродействие, интересно, что получится Улыбаюсь ) :
Код:
(то что ниже - не проверял - только в теории,)
{
   задаём цвет new и old. помещаем в стек затравку(пиксел, с
   которого начинаем заливку).;
   while(стек не пуст)
   {
      достаём из стека пиксел P;
      if(цвет P != new)
      {
         красим P в цвет new;

         if(сверху от P находится пиксел НЕ цвета old)
         {
            помещаем пиксел сверху от P в стек ;
         }

         if(снизу от P находится пиксел НЕ цвета old)
         {
            помещаем пиксел снизу от P в стек ;
         }

         P1=P;
         while(можно двигаться влево от P1)
         {
            P1 = пиксел слева от P1;
            красим P1 в new;
            if(справа_сверху от P1 находится пиксел НЕ цвета old)
            {
               помещаем пиксел сверху от P1 в стек;
            }

            if(справа_снизу от P1 находится пиксел НЕ цвета old)
            {
               помещаем пиксел снизу от P1 в стек;
            }

         }

         P1=P;
         while(можно двигаться вправо от P1)
         {
            P1 = пиксел справа от P1;
            красим P1 в new;

            if(слева_сверху от P1 находится пиксел НЕ цвета old)
            {
               помещаем пиксел сверху от P1 в стек;
            }

            if(слева_снизу от P1 находится пиксел НЕ цвета old)
            {
               помещаем пиксел снизу от P1 в стек;
            }

         }
      }////if(цвет P != new)
   }
}

извини - в коде реализовать не успею опять. Попробуй сам. Не забывай следить за границами координат (смотри по конкретной ситуации).

Цитата
к примеру треугольник ну и пусть равнобедренный. Так вот заполняться он будет так:
Нарисуется линия от правого края до левого, затем все что сверху будет заполняться нормально, а вот то что снизу нет. Снизу получится как бы залитый квадрат, т.е. от места первоначальной затравки и вниз правая сторона треугольника удаляется, а вот линии рисуются не от края стороны, а от значения Х крайней правой точки там где рисовалась первая полоса.
опять же - может быть из-за неправильного описания массива. Запросто.
на сегодня всё - сплю на ходу...
Завтра ещё загляну
« Последнее редактирование: 02-12-2007 15:59 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #11 : 27-10-2004 19:50 » 

вот эти участки твоего кода слегка подозрительны:
(я не менял, а так же расписал поровнее)

 :arrow:
   mass[0][0]=NULL;
   mass[1][0]=NULL;

эх, не слушаешь советов... Пиши :
   mass[0][0]=0;
   mass[1][0]=0;


 :arrow:
Код:
      //////////////////////////////3begin//////////////////////
   if(schet==0)
   {
      mass[0][0]=NULL;mass[1][0]=NULL;
   }
   else
      for(int i=0; i<schet;i++)
      {
         mass[0][i]=mass[0][i+1];
         mass[1][i]=mass[1][i+1];
      }


      mass[0][schet]=NULL;  ///
      mass[1][schet]=NULL;  ///
      schet--;                      ///
   }
   ///////3End//////////
   delete []mass;

смотри - три строки , отмеченные "///" выполнятся независимо от условия
if(schet==0)
возможно так и надо, но - я просто обращаю внимание

 :arrow:
   delete []mass;
неправильно память освобождаешь. если ты делал
mass=new unsigned long *[2];
mass[0]=new unsigned long [50];
mass[1]=new unsigned long [50];

, то и удаляй так же:
delete [] mass[0];
delete [] mass[1];
delete [] mass;

на большее меня тоно не хватит сегодня Улыбаюсь  :new_shot:
« Последнее редактирование: 02-12-2007 16:01 от Алексей1153++ » Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 28-10-2004 01:13 » 

Прочитать успел, а вот ответить боюсь не успею Жаль, вечером отпишусь, а по поводу mass[0][0]=NULL, исправлю, просто не обратил внимание, но я в принципе давно так делаю и никогда  не жаловался, но все равно лучше и вправду исправить.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #13 : 28-10-2004 18:00 » 

вот код, который я сделал из твоего кода , расположенного четырьмя постами выше. ЛОГИКУ не менял. Только явные косяки исправил и заменил проверку граничного цвета на проверку границ прямоугольника (0,0,xmax,ymax) . Проверку на нехватку стека заливки mass я не произвожу. (но это неправильно Улыбаюсь )

не удивляйся некоторым изменениям внешнего вида Улыбаюсь , просто проверку кода я делал в проге ShelekToy, заменив свой алгоритм заливки твоим (потому что придумывать фантик сейчас нет сил). Чтобы сильно не менять твой текст (в частности переменную hdc) я вклеил макрос

#define hdc(x,y) CurrPict[y*CurrWidth+x]

и теперь
old=hdc(x,y);
эквивалентно твоему
hdc(x,y)->GetPixel(x,y);

а
hdc(x,y)=new;
эквивалентно твоему
hdc(x,y)->SetPixel(x,y,new);

CurrWidth и CurrHeight – это ширина и высота моего растра.
я их кладу сюда:
long xmax=CurrWidth-1;
long ymax=CurrHeight-1;

кстати - вместо ULONG для координат использую тип long. Так даже в MFC-процедурах

и ещё одна моя эгоистичная Ага просьба - придерживайся такого вида кода, как я написал. Так мне проще разбираться - а каждый раз приводить твой код в порядок тяжело. Да и тебе самому проще станет ошибки выцеплять Улыбаюсь

короче - проследи ещё раз логику, там где я понял, что ты делаешь, я писал свои комментарии, а где я потерял мысль - там нет комментариев. Ещё - пиши обильные комментарии, самому проще будет. А мне разбираться в чужих мыслях - тем паче Улыбаюсь . Ниже кода - мои замечания по ходу

Код:
#define hdc(x,y) CurrPict[y*CurrWidth+x]

void CstatPICT::OnRBD(UINT nFlags, CPoint point)
{
int x,y;
//координаты клетки, по которой щелкнули
x=point.x;
y=point.y;

//проверка на границы
if( x>=0 && x<CurrWidth && y>=0 && y<CurrHeight )
{
// Заливка
//void ::zapoln(CPoint point, COLORREF old, COLORREF nov,COLORREF gran, CDC *hdc)

COLORREF old=CurrPict[y*CurrWidth+x];
COLORREF nov=theApp.theView->m_statCURRCOLOR.CurrColor;
long xmax=CurrWidth-1;
long ymax=CurrHeight-1;

//unsigned long x=point.x, y=point.y;//, xl, yl, xr, yr;
long xrn=0;//правый нижний
long xln=0;//левый нижний
long xrv=0;//правый верхний
long xlv=0;//левый верхний
long xl=0;//самый левый
long xr=0;//самый правый
long xrrez=0; //?
int schet=0;
int kolvo=0;
int flag=0;
int fl=0;

//создаём стек заливки
long **mass;

#define _x 0
#define _y 1

mass=new long *[2];
mass[_x]=new long [CurrWidth*CurrHeight];
mass[_y]=new long [CurrWidth*CurrHeight];
mass[_x][0]=0;
mass[_y][0]=0;

//////1begin////////
//двигаясь от затравки, ищем крайнюю правую
//точку, не закрашенную цветом old
for(xr=x; xr<xmax && hdc(xr+1,y)==old ;xr++);

//кладём в стек
mass[_x][schet]=xr;
mass[_y][schet]=y;
schet++;
////////1end/////////

////Obschiy Cycl///////
while( mass[_x][0] && mass[_y][0])
{
flag=0;
fl=0;
//копируем из вершины стека, но не удаляем (!!!косяк)
x=mass[_x][0];
y=mass[_y][0];

///////////////Kraynie Tochki//////////////////////
xr=xrrez=x;
////////////////

//проверка существования пиксела слева сверху
if( xr-1>=0 && y+1<=ymax)
{
//если пиксел сверху == old или ==nov,
//то кладём в стек
if(hdc(xr,y+1)==old || hdc(xr,y+1)==nov)
{
mass[_x][schet]=xrv=xr;
mass[_y][schet]=y+1;
schet++;
}
else
{
//если пиксел слева сверху == old или ==nov,
//то кладём в стек
if(hdc(xr-1,y+1)==old || hdc(xr-1,y+1)==nov)
{
xr--;
//Zapis v mass i uvelichenie schetchika
mass[_x][schet]=xrv=xr;
mass[_y][schet]=y+1;
schet++;
}
}
}
else
{
//двигаемся вправо, пока пиксел сверху от
//текущего  == old или ==nov
while(hdc(xr,y+1)==old || hdc(xr,y+1)==nov)
{
xrv=xr;
xr++;
}
//Zapis elementov v mass
mass[_x][schet]=xrv;
mass[_y][schet]=y+1;
schet++;
}

//////===================//////

//KRAYNAYA TOCHKA VNIZU SPRAVA
xr=xrrez=x;

if (xrrez-1>=0 && y-1>=0)
{
if(hdc(xrrez,y-1)==old || hdc(xrrez,y-1)==nov)
{
//Zapis v massiv
mass[_x][schet]=xrn=xrrez;
mass[_y][schet]=y-1;
schet++;
}
else
{
if( hdc(xrrez-1,y-1)==old || hdc(xrrez-1,y-1)==nov )
{
xrrez--;
mass[_x][schet]=xrn=xrrez;
mass[_y][schet]=y-1;
schet++;
}
}
}
else
{
while(hdc(xrrez,y-1)==old || hdc(xrrez,y-1)==nov)
{
xrn=xrrez;
xrrez++;
}
///Zapis elementov v mass
mass[0][schet]=xrn;
mass[1][schet]=y-1;
schet++;
}


//////2begin//////
while( x>0 && hdc(x-1,y)==old)
{
hdc(x,y)=nov; //закрашиваем
x--;
}
//////2end////////

/////3begin///////

if(schet==0)
{
mass[_x][0]=0;
mass[_y][0]=0;
}
else
{
//сдвигаем стек, уничтожая НИЖНИЙ элемент
//(!!! по-моему - косяк )
for(int i=0; i<schet;i++)
{
mass[_x][i]=mass[_x][i+1];
mass[_y][i]=mass[_y][i+1];
}
}

//в освободившийся верх стека кладём ноль
//(тут, если честно, я теряю твой нить
//рассуждений :) )
mass[_x][schet]=0;
mass[_y][schet]=0;
schet--;

} //while( mass[_x][0] && mass[_y][0])

///////3End//////////
delete [] mass[_x];
delete [] mass[_y];
delete [] mass;

RedrawWindow();
}
}

 :arrow:
 попытка запустить код на исполнение закрасила немного , а после этого вызвала удивление y Windows, в чего, собственно , и следовало Ага

 :arrow:
не используются переменные:
   long xln=0;
   long xlv=0;//левый верхний
   long xl=0;//самый левый
   int kolvo=0;
   int flag=0;
   int fl=0;

 :arrow:
Код:
//копируем из вершины стека, но не удаляем (!!!косяк)
x=mass[_x][0];
y=mass[_y][0];

///////////////Kraynie Tochki//////////////////////
собственно - элемент не извлекается, а только копируется. Он ОСТАЁТСЯ в стеке. Надо ли так?

 :arrow:
Код:
//сдвигаем стек, уничтожая НИЖНИЙ элемент
//(!!! по-моему - косяк )
for(int i=0; i<schet;i++)
{
mass[_x][i]=mass[_x][i+1];
mass[_y][i]=mass[_y][i+1];
}
повторяю - не знаю твоей логики, словесный алгоритм ты так и не написал. Но обычно удаляется элемент из вершины стека (а как я понял - тут происходит удаление элемента) , то есть не с нулевым номером, а с максимальным. Та принято...
И ещё - если работаешь со стеком, то операцию извлечения из стека надо делать в одном месте кода : копируем из вершины стека элемент и тут же удаляем этот элемент из стека. А у тебя, насколько я понял, эти части операции извлечения разнесены в разные участки кода

ну вот пока всё - жду ответа.
« Последнее редактирование: 02-12-2007 16:04 от Алексей1153++ » Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 28-10-2004 19:43 » 

Вечер добрый, благодарен за то, что не покидаешь/ете  меня Улыбаюсь.
Так теперь по порядку:

замечания по поводу структуры кода понял, в следующий раз исправлюсь.
по поводу того, что не используется ряд переменных, это еще с прошлой разработки, вначале лень было удалять, а потом забыл про них совсем, поэтому они просто тихо мирно жрут ресурсы Улыбаюсь.

Так, а теперь, чтобы пропало недопонимание между нами СЛОВЕСНЫЙ АЛГОРИТМ:
1) получаю координаты точки, с которой пользователь решил проводить заливку
2) смещаюсь вправо до тех пор пока не дойду до границы области и тем самым получаю крайнюю правую точку
3) заношу ее в стек

начинается цикл который проводится на протяжении всей заливки  
4) получаю точку (координаты) из стека (точку беру СВЕРХУ)  
5) затем начинаю искать крайние правые точки выше и ниже точки которую получили из стека  
6) найдя крайние правые точки, заношу их в конец стека
7) затем рисуется линия от точки полученной на шаге (4). Линия рисуется только влево, т.к. точка крайняя правая. Линия рисуется до тех пор, пока не будет встречен цвет границы
8)удаляю первый (ВЕРХНИЙ) элемент стека и сдвигаю все элементы на одно значение вверх. (В принципе удаление происходит таким образом, что первый элемент затирается вторым, второй третьим и т.д. )
9) переходим к шагу  (4). Выходим в случае если первый элемент стека равен NULL (условие выхода конечно не ахти, но пока можно и так оставить)

Вроде нигде не ошибся, надеюсь что написал понятно.

По поводу того что если взял из стека, то и удали - я с этим согласен, не знаю почему я удаляю позже, это исправлю, но я думаю это никак не влияет на корректность кода (проги).
Точка xrrez нужна когда ищу крайнюю правую точку сверху (но по сути это лишняя переменная, достаточно было бы присвоить xr значение х и использовать её).

Но и насчет того что я удаляю нижний элемент из стека. Если я нигде не ошибся, то идея была удалить ВЕРХНИЙ элемент из стека, т.к. он уже закрашен.

Напоследок, впринципе при тесте проги я выводил контрольные точки и прослеживал работу со стеком в частности и рискну заявить, что она проходит корректно: новые элементы заносятся в стек (именно в конец стека), удаляется самый первый элемент (ВЕРХНИЙ), поэтому просьба просмотреть еще раз этот кусок, по-моему я там нигде не ощибался. Я считаю, что ошибся в шаге (5), я писал выше из-за чего я сделал такие выводу (там где треугольник).
Кстати кусок который я выслал тебе/Вам (возраста не знаю, боюсь обидеть) должен закрашивать квадрат, я проверю то ли я выслал, а с другими областями (формами) проблема (об этом я также писал выше).

Вроде ничего не забыл.
P.s. к сожалению обстоятельства сложились так, что до субботы у меня не будет возможности повозиться с этой прогой (тут упало ряд новых проблем), поэтому код высланный тобой/Вами я протестирую в субботу, и опять начну искать ошибку. На форум заходить буду, мало ли что, но пока (в пятницу) от меня никаких действий по поводу проги не ожидается.
Спасибо за внимание, до связи Улыбаюсь.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #15 : 29-10-2004 03:22 » 

Цитата

что не покидаешь/ете меня


я не "ете" Ага

 :arrow:
Цитата

СЛОВЕСНЫЙ АЛГОРИТМ

посмотрю, завтра наверное только

 :arrow:
Цитата

Напоследок, впринципе при тесте проги я выводил контрольные точки и прослеживал работу со стеком в частности и рискну заявить, что она проходит корректно: новые элементы заносятся в стек (именно в конец стека), удаляется самый первый элемент (ВЕРХНИЙ), поэтому просьба просмотреть еще раз этот кусок, по-моему я там нигде не ощибался.

посмотрю, возможно ты и не ошибся, я не знаю какой тип стекаты используешь - fifo или filo. Я имею в виду FILO - то есть "fist in - last out" , если элемент первый помещён, то удалится последним. Там верхний элемент - это САМЫЙ ПОСЛЕДНИЙ
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 29-10-2004 13:08 » 

Цитата
я не ете
- это хорошо Улыбаюсь.
Тип стека, который я использую - FIFO.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #17 : 30-10-2004 02:48 » 

лучше filo, потому как он быстрее работает. Вот смотри:

 :arrow: стек fifo

1)помещение элемента в начало стека и извлечение элемента из конца стека - это одно действие, даже если оно (как у тебя) разнесено в разные участки кода. То есть это конвеер. Ты двигаешь этот конвеер, перемещая элементы стека. А это долго.

 :arrow: стек filo
1)указатель стека, равный нулю говорит о том, что стек пуст.
2) помещение элемента в стека , это: запись элемента в стек по смещению (адресу) которое записано в указателе, затем увеличение указателя на единицу.
3)извлечение элемента из стека - уменьшение указателя на единицу и чтение элемента с адреса, которое записан в указателе

заметь - никаких занимающих кучу времени сдвигов всего массива, а все остальные подобные действия есть и в fifo. Кроме того - размер стека задаётся максимальным значением указателя стека и его можно свободно динамически увеличивать, не нарушая структуры стека

мои процедуры (верхний пост) push и pop - это и есть стек filo
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 06-11-2004 14:14 » 

Извеняюсь, что  неожиданно пропал из вида, были дела хреновые, но я пишу в эту наполовину закрытую тему, чтобы довести её до логического конца. Я нашел (наконец-то) ошибку, как и предполагалось она была в поиске крайних точек и ни в чем другом, не массив, не прочее. Но все же кое-какие огрехи я исправил, остальные исправлю позже (типа delete []mass и пр.). самое главное, что прога стала вначале заполнять просто области любой формы, но без помех, ну а теперь, я добавил пару операторов, и вот практически полный PAINT Улыбаюсь . Осталось добавить динамическое распределение памяти массиву, по мере необходимости, переделать тип из unsigned long в long и условием выхода из цикла сделать не NULL , а -1.  Но это уже не проблема. А пишу прямо сейчас в форум, не доделав прогу, потому, что охота все-таки поделиться маленькой радостью и размышлениями по поводу того, как легко что-то написать, но как потом тяжело в этом искать баги Жаль. Я выкладываю код того, что у меня на данный момент есть и надеюсь. Это еще вызванно тем, что Алексей 1153 предлагал сравнить скорости прог заполнения. Ну что ж, я не против, даже наоборот "за", хотя уверен, что твоя прога, Алексей1153, быстрее, но ради эксперимента... Улыбаюсь.
  Я постараюсь структуировать код, так как смогу, буду очень стараться, заранее извеняюсь за карявость. В некоторых новых местах кода буду ставить комментарии.

Объявление переменных и сдвиг точки запуска функции к правой границе:
Код:
void zapoln(CPoint point, COLORREF old, COLORREF nov,COLORREF gran, CDC *hdc)
{



unsigned long x=point.x, y=point.y;
unsigned long xrn=0,  xrv=0, xr=0,xrrez=0;
int schet=0, kolvo=0, flag=0, fl=0;
    unsigned long **mass;

mass=new unsigned long *[2];
  mass[0]=new unsigned long [50];
  mass[1]=new unsigned long [50];
  mass[0][0]=NULL; mass[1][0]=NULL;
               
  for( ;hdc->GetPixel(x,y)==old;x++)
{; }
       
--x;

  xr=x;
             schet=0;

                   mass[0][schet]=x; mass[1][schet]=y;
   schet++;


Цикл заполнения области:

Код:
for(;mass[0][0]!=NULL || mass[1][0]!=NULL;)
 
 {
   
 
     flag=0; fl=0;
   x=mass[0][0]; y=mass[1][0];



Начинается поиск крайних правых точек:
Поиск точки сверху:
Код:
xr=xrrez=x;    


if(hdc->GetPixel(xr,y-1)==gran && hdc->GetPixel(xr-1,y-1)==old)
{ xrv=xr-1; mass[0][schet]=xrv; mass[1][schet]=y-1; schet++;}

    if(hdc->GetPixel(xr+1, y-1)==gran && hdc->GetPixel(xr,y-1)==old)
    {xrv=xr; mass[0][schet]=xrv; mass[1][schet]=y-1; schet++;}
       
           if(hdc->GetPixel(xr,y-1)==old && hdc->GetPixel(xr+1,y-1)==old )
           { xrv=xr;
              for(;hdc->GetPixel(xrv+1,y-1)==old;xrv++)
                {;}
                mass[0][schet]=xrv; mass[1][schet]=y-1; schet++; 
   }
 
  if(hdc->GetPixel(xr,y-1)==gran && hdc->GetPixel(xr-1,y-1)==gran)
{ xrv=xr;
for(;hdc->GetPixel(xrv,y-1)==gran && hdc->GetPixel(xrv,y)!=gran;xrv--)
{;}
if(!(hdc->GetPixel(xrv,y-1)==gran && hdc->GetPixel(xrv,y)==gran))
{mass[0][schet]=xrv; mass[1][schet]=y-1; schet++;}
   }

как видно я переделал поиск крайних точек, не дюже сильно, но все же. Как раз здесь укажу на мою ошибку: Это последнее  условие:
вот оно (кстати его вставлять не надо-это повторение из предыдущего кода)
Код:
if(hdc->GetPixel(xr,y-1)==gran && hdc->GetPixel(xr-1,y-1)==gran)
{ xrv=xr;
for(;hdc->GetPixel(xrv,y-1)==gran && hdc->GetPixel(xrv,y)!=gran;xrv--)
{;}
if(!(hdc->GetPixel(xrv,y-1)==gran && hdc->GetPixel(xrv,y)==gran))
{mass[0][schet]=xrv; mass[1][schet]=y-1; schet++;}
  "

аннологично и для поиска крайней правой точки на нижней строке.
Поиск крайней точки в нижней строке

Код:
if(hdc->GetPixel(xrrez,y+1)==gran && hdc->GetPixel(xrrez-1, y+1)==old)
{xrn=xrrez-1; mass[0][schet]=xrn; mass[1][schet]=y+1; schet++;}
   
if(hdc->GetPixel(xrrez+1, y+1)==gran && hdc->GetPixel(xrrez,y+1)==old)
     {xrn=xrrez; mass[0][schet]=xrn; mass[1][schet]=y+1; schet++;}

if(hdc->GetPixel(xrrez,y+1)==old && hdc->GetPixel(xrrez+1,y+1)==old)
{xrn=xrrez;
                   for(;hdc->GetPixel(xrn+1,y+1)==old;xrn++)
                     {;}
     mass[0][schet]=xrn; mass[1][schet]=y+1; schet++;}

 if(hdc->GetPixel(xrrez,y+1)==gran && hdc->GetPixel(xrrez-1,y+1)==gran)
                                    {xrn=xrrez;
for(;hdc->GetPixel(xrn,y+1)==gran && hdc->GetPixel(xrn,y)!=gran;xrn--)
  {;}

 if(!(hdc->GetPixel(xrn,y+1)==gran && hdc->GetPixel(xrn,y)==gran))
  {mass[0][schet]=xrn; mass[1][schet]=y+1; schet++; }
}
Здесь все аналогично.
Теперь идет заполнение пикселями строк и при этом осуществляется сканирование верхних и нижних строк (это уже прибамбас, чтобы заливать область с помехами).
Код:
for(;hdc->GetPixel(x,y)==old;)
{

hdc->SetPixel(x,y,nov);
--x;

Начинается сканирование под этим пикселем(прорисованным)
Код:
COLORREF a=hdc->GetPixel(x+1,y+1);     
if (a==gran)
flag=1;
else
{
if(flag==1)
{ mass[0][schet]=x; mass[1][schet]=y+1; schet++;}
flag=0;
}


Теперь над пикселем
Код:
a=hdc->GetPixel(x+1,y-1);
if (a==gran)             //dlya nijney stroki
fl=1;
else
{
if(fl==1)
{mass[0][schet]=x; mass[1][schet]=y-1; schet++; }
fl=0;
}
/////////////////////Скобка закрытия цикла

}

Теперь удаление из стека, использованной верхней точки, а также проверка на нахождения в стеке точек, которые уже закрашены. Это в принципе лишнее, т.к. их там быть не может, но я оставил, на всякие пожарные

Код:
  if(schet==0)
|mass[0][0]=NULL;mass[1][0]=NULL;}
else
  for(int i=0; i<schet;i++)

|mass[0][i]=mass[0][i+1];
mass[1][i]=mass[1][i+1];}
mass[0][schet]=NULL;
mass[1][schet]=NULL;
schet--;
///////////////////////////////////
proverk_mass(mass,schet,nov,gran,old,hdc);
}

/////////////////////////////////


delete []mass;
}

Я помню, что ты, Алексей1153, мне советовал, по поводу того, что из стека надо удалять сразу, потом исправлю.

 Ну и теперь пара функций которые в принципе не нужны если выкинуть proverk_mass, но мне интересно, в каком слечае прога быстрее работает с proverk_mass или без этой функции

Код:
////==Sortirovka Massiva=============/////////////////
int sortmass (int j, int schet, unsigned long **mass)
{
if(schet==0)
|mass[0][0]=NULL;mass[1][0]=NULL;}
else
{ for (int i=j; i<schet;i++)
|mass[0][i]=mass[0][i+1];
mass[1][i]=mass[1][i+1];}

 mass[0][schet]=NULL;
 mass[1][schet]=NULL;
 --schet;}
 
return schet;
}

//////============Proverka Massiva=======//////////////

 void proverk_mass(unsigned long **mass, int schet,COLORREF nov,COLORREF gran,COLORREF old, CDC *hdc)
{
for(int i=0; i<schet; i++)  //???
{
                 if(hdc->GetPixel(mass[0][i],mass[1][i])==nov)
{
schet=sortmass(i,schet,mass);}
   }

}
Я не стал менять эти функции, и даже не пробовал, поэтому если где в них естьбаг, то это нормально Улыбаюсь, хотя они не мешают корректному выполнению проги.

 Ну, надеюсь не зря были мои старания и ты Алексей 1153, прочитаешь все это и может даже протестируешь, тогда обязательно скажи (напиши) результаты. И хотел бы поблагодарить тебя за то, что ты откликнулся на мой зов о помощи, ты оказался единственным, спасибо за помощь и вообще... Улыбаюсь.
« Последнее редактирование: 02-12-2007 16:18 от Алексей1153++ » Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #19 : 06-11-2004 20:04 » 

nikedeforest, рад за твою победу Ага

если честно, я и не помогал - ты вроде сам всё и сделал

 :arrow:
Цитата
хотя уверен, что твоя прога быстрее, но ради эксперимента...
а я совершенно не уверен Улыбаюсь , пока не сравнить - не узнать. Просто часто бывает так, что код короткий (как тот, что у меня), но работает долго, а код длиннее - работает и быстрее за счёт проверки дополнительных условий, позволяющих не выполнять по нескольку раз одни и теже действия (закраска одного пиксела по нескольку раз). В то же время - может статься так, что 10 раз закрасить пиксел это быстрее, чем выполнить дополнительную процедуру, которая определит, что ещё 9 раз красить не нужно...

короче - тут только опытным путиным

 :arrow: пробовать мне сейчас, к сожалению, некогда. Если интересно - замени свою процедуру моим кодом (осмысленно, естественно, а не просто copypaste) и сравни время закраски одной и той же области раз, скажем 1000.
-----------------
а динамически менять размер FILO стека так (сам принцип):

Код:
DWORD len; // здесь - текущая длина стека
len=50;

long *S=new long[len]; //создали стек
DWORD num=0;//хранит количество элементов в стеке
...
Код:
//помещаем элемент в стек
void push(long element)
{
 
    //определяем переполнение
    if(num==len)
    {
        //стек заполнен по нехочу
        enlargeStackX2();//увеличиваем в два раза
    }
    S[++num]=element;
}

//увеличиваем стек в два раза
void enlargeStackX2()
{
    //новая длина
    DWORD newlen=len<<1;

    //создаём новый стек
    long *newS=new long[newlen];

    //копируем старый стек в новый
    // for(DWORD i=0;i<len;i++) newS[i]=S[i];
    ::memmove(newS,S,newlen*sizeof(*newS));

    //удаляем старый стек
    delete [] S;

    //настраиваем указатель
    S=newS;

    //настраиваем длину
    len=newlen;
}

то есть размер увеличится "в фоне", как-бы совершенно не влияя на остальной процесс

 :arrow:
Цитата
Я не стал менять эти функции, и даже не пробовал, поэтому если где в них естьбаг, то это нормально
это неправильный подход. Теперь, когда в мыслях у тебя сформирован образ, когда ты уже знаешь лазейки и источники возможных ошибок - пересматриваешь код и ищешь баги. Если кажется, что баги есть - они есть, даже если их нет Ага . Вот когда уверен, что багов нет - их нет примерно на 50%. У меня так было много раз - и вот недавно, практически только что, - исправишь одно, а оно приоткрывает ранее неизвестную и не проявившуюся ошибку...

 :arrow:
короче - если что - всегда спрашивай, тут тебе всегда кто-нибудь поможет   Улыбаюсь
« Последнее редактирование: 02-12-2007 16:24 от Алексей1153++ » Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 07-11-2004 14:58 » 

Cпасибо на добром слове. С динамикой обязательно разберусь, да и баги остальные исправлю, но просто надо еще другие дела довершить Жаль , как только так сразу Улыбаюсь.
Вот тут делаю другую прогу и нарисовался вопрос, интересно это ведь надо новую тему создавать, наверное так и сделаю, хотя жаль эту закрывать мы тут в сумме Войну и Мир накатали новый том Улыбаюсь.
"Пойду" новую тему создавать (в этом же разделе форума), вопрос кстати несложный для нормальных программеров, я просто с Visual C++ практически только начинаю работать и проблемы в принципе детские, поэтому  для тебя Алексей1153 проблем не составит ответить, время будет зайди, посмотри.
 Ну до новых встреч Улыбаюсь
p.s. У меня на эту тему почтовое уведомление, поэтому если ты что сюда напишишь, тоя об этом обязательно узнаю и обязательно отвечу.
Еще раз- до новых встреч.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #21 : 07-11-2004 19:48 » 

nikedeforest, если нужно найти все новые темы или новые ответы на темы - то когда залогиниваешься, нажимай вверху страницы ссылку
"найти все сообщения с последнего посещения"

а ещё проще - когда щёлкнешь по ссылке и откроется окне браузера с найденными темами - нажми Ctrl+D - и в последующих разах просто сразу запускай этот адрес Улыбаюсь
Я так и делаю постоянно. А если поставить галочку автологина (если комп домашний, конечно) - то ваще лафа  Отлично
Записан

nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 08-11-2004 13:55 » 

Хороший алгоритм, понятный, простой в реализации, действенный. Я хотел, чтобы в случае нехватки места в стеке увеличение стека шло на один элемент, но это неправильно, по времени долго и вообще, а 50 элементов это нормально Улыбаюсь.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #23 : 08-11-2004 17:47 » 

ну так, естественно, если не хватило места, то само собой, что добавлением одного элемента тут не отмахнёшься Улыбаюсь . А вот в два раза - самое то.

Попробуй закрасить такую фигуру

8888888888888888888888888888888888888888888888888888
88888888888888
88888888888888888888888888888888888888
8888888888
888888888888888888888888888888888888888888
88888888
88888888888888888888888888888888888888888888
888888
8888888888888888888888888888888888888888888888
888888
8888888888888888888888888888888888888888888888
8888
888888888888888888888888888888888888888888888888
8888
888888888888888888888888888888888888888888888888
8888
888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
88
88888888888888888888888888888888888888888888888888
8888
888888888888888888888888888888888888888888888888
8888
888888888888888888888888888888888888888888888888
88888888
88888888888888888888888888888888888888888888
8888888888
888888888888888888888888888888888888888888
88888888888888
88888888888888888888888888888888888888
8888888888888888888888888888888888888888888888888888


то есть залить белый цвет другим - начиная с чёрного крестика
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines