gjrbyek ajhev
Отредактировано Webarion (13.06.2025 13:07:53)
PureBasic - форум |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.
gjrbyek ajhev
Отредактировано Webarion (13.06.2025 13:07:53)
Что то подобное мутил,только в массиве
Structure koordinaty x.i y.i x1.i y1.i EndStructure Structure ikrangadgeta koordinatyikrana.koordinaty HDC.i Fon.i Shrift.i ControlFon.i count.l EndStructure Structure control *text textlen.l id.a koordinatycontrola.koordinaty ;ControlFon.i EndStructure Global ikrangadgeta.ikrangadgeta ikrangadgeta\count=-1 Global Dim control.control(0) Procedure.l HandleError(Result.l,Text$,flag.i=0);Вывод еррор сообщений If Result=0 MessageRequester("Error",Text$,flag) Else ProcedureReturn Result EndIf EndProcedure Procedure Len_UTF16R(*s);возврат количество символов !mov eax,DWORD PTR esp+4 !hut15: !CMP word ptr eax,0h !Je rr15 !add eax,4 !CMP word ptr eax-2,0h !Jnz hut15 !sub eax,2 !rr15: !SUB eax,DWORD PTR esp+4 !Sar eax,1 !retn 4 EndProcedure Procedure Customgadget(id,x,y,x1,y1,texst.s) Protected r.i !mov dword eax,[esp+40] !mov dword [p.v_r],eax ikrangadgeta\count+1 If ikrangadgeta\count>0 ReDim control.control(ikrangadgeta\count) EndIf control(ikrangadgeta\count)\text=r control(ikrangadgeta\count)\textlen=Len_UTF16R(control(ikrangadgeta\count)\text) control(ikrangadgeta\count)\koordinatycontrola\x=x control(ikrangadgeta\count)\koordinatycontrola\x1=control(ikrangadgeta\count)\koordinatycontrola\x+x1 control(ikrangadgeta\count)\koordinatycontrola\y=y control(ikrangadgeta\count)\koordinatycontrola\y1=control(ikrangadgeta\count)\koordinatycontrola\y+y1 control(ikrangadgeta\count)\id=id EndProcedure Procedure vyvodcontrola(prioritet.i) Protected lenstr.i Protected i.i ;StartDrawing(CanvasOutput(1)) ;Box(0, 0, 800,500, $FFFFFF) FillRect_(ikrangadgeta\HDC,@ikrangadgeta\koordinatyikrana,ikrangadgeta\Fon) For i=0 To ikrangadgeta\count ;Debug 888888888 If i<>prioritet FillRect_(ikrangadgeta\HDC,@control(i)\koordinatycontrola,ikrangadgeta\ControlFon) ;Rectangle_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x, control(i)\koordinatycontrola\y,control(i)\koordinatycontrola\x1,control(i)\koordinatycontrola\y1) ;FrameRect_(ikrangadgeta\HDC, @control(i)\koordinatycontrola, $070808) MoveToEx_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x,control(i)\koordinatycontrola\y,0); LineTo_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x1,control(i)\koordinatycontrola\y) LineTo_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x1,control(i)\koordinatycontrola\y1) LineTo_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x,control(i)\koordinatycontrola\y1) LineTo_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x,control(i)\koordinatycontrola\y) TextOut_(ikrangadgeta\HDC,control(i)\koordinatycontrola\x,control(i)\koordinatycontrola\y,control(i)\text,control(i)\textlen) ;ExtTextOut_(Texthdc,x.i,y.i,options.i,*RECT,*lpString,c.i,*lpDx ) EndIf Next FillRect_(ikrangadgeta\HDC,@control(prioritet)\koordinatycontrola,ikrangadgeta\ControlFon) MoveToEx_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x,control(prioritet)\koordinatycontrola\y,0); LineTo_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x1,control(prioritet)\koordinatycontrola\y) LineTo_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x1,control(prioritet)\koordinatycontrola\y1) LineTo_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x,control(prioritet)\koordinatycontrola\y1) LineTo_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x,control(prioritet)\koordinatycontrola\y) TextOut_(ikrangadgeta\HDC,control(prioritet)\koordinatycontrola\x,control(prioritet)\koordinatycontrola\y,control(prioritet)\text,control(prioritet)\textlen) ;DrawImage(ImageID(0), WindowMouseX(0), WindowMouseY(0)) ;StopDrawing() EndProcedure Procedure move(clik.i) Protected numberobject.i;для поиска объекта,переменная среда от 0 и выше на выход найденного объекта,если объект найден по клику то его ;индекс заносится в переменную ocnoobjecta для дольнейшего действия на перемещение мыши,если нет то бездействие и по отпускании кнопки мыши ;возврат в исходное состояние (объект не найден,ocnoobjecta=-1) Static ocnoobjecta.i=-1 Static prioteretobjecta.i;есле объект накладывается поверх другого для отрисовки Static xy.Point Static xy1.Point Static xy2.Point If clik=2; If ocnoobjecta>-1 GetCursorPos_(@xy2) ScreenToClient_(GadgetID(1), @xy2) Debug xy2\y control(ocnoobjecta)\koordinatycontrola\x=xy2\x-xy\x control(ocnoobjecta)\koordinatycontrola\x1=xy2\x+xy1\x control(ocnoobjecta)\koordinatycontrola\y=xy2\y-xy\y control(ocnoobjecta)\koordinatycontrola\y1=xy2\y+xy1\y vyvodcontrola(ocnoobjecta) EndIf ElseIf clik=1 GetCursorPos_(@xy) ScreenToClient_(GadgetID(1), @xy) ;xy\x+GetGadgetAttribute(0, #PB_ScrollArea_X) ;xy\y+GetGadgetAttribute(0, #PB_ScrollArea_Y) ; For numberobject=0 To ikrangadgeta\count If xy\x>control(numberobject)\koordinatycontrola\x And xy\x<control(numberobject)\koordinatycontrola\x1 If xy\y>control(numberobject)\koordinatycontrola\y And xy\y<control(numberobject)\koordinatycontrola\y1 ocnoobjecta=numberobject ;prioteretobjecta=numberobject ;вычислим разницу от краёв x,y объекта и x,y точки клика,и запомним её xy1\x=control(numberobject)\koordinatycontrola\x1-xy\x xy\x-control(numberobject)\koordinatycontrola\x xy1\y=control(numberobject)\koordinatycontrola\y1-xy\y xy\y-control(numberobject)\koordinatycontrola\y Continue; ;Debug xy\y EndIf EndIf Next ; ElseIf clik=0 ocnoobjecta=-1 ElseIf clik=3;#WM_RBUTTONDOWN GetCursorPos_(@xy) ScreenToClient_(GadgetID(1), @xy) For numberobject=0 To ikrangadgeta\count If xy\x>control(numberobject)\koordinatycontrola\x And xy\x<control(numberobject)\koordinatycontrola\x1 If xy\y>control(numberobject)\koordinatycontrola\y And xy\y<control(numberobject)\koordinatycontrola\y1 SetGadgetState(990,numberobject+1) Continue; EndIf EndIf Next EndIf EndProcedure Procedure Canvas_calbak(hwnd,msg,wparam,lparam) Static Rodnoy_calbak.i Static a.a Protected Rezultat.i If Not msg=1 Rezultat=CallWindowProc_(Rodnoy_calbak, hWnd, Msg, wParam, lParam);сначала прыгнем в родной обработчик EndIf ;Debug msg Select msg Case #WM_CREATE ;ScrollAreaGadget(0, 0, 60, 800,500,5000,5000,100) ;SetGadgetAttribute(0, #PB_ScrollArea_X ,2500);установка ползунка по х ;CanvasGadget(1, 0, 0,5000,5000,#PB_Screen_SmartSynchronization) ;GetClientRect_(GadgetID(1),@ikrangadgeta\koordinatyikrana);запишим полученные координаты экрана ;InvalidateRect_(GadgetID(2), 0, #True) ;ikrangadgeta\HDC=GetDC_(GadgetID(1));запишим контекст рисования ;SetBkMode_(ikrangadgeta\HDC,#TRANSPARENT);#TRANSPARENT(цвет фона прозрачный,остается нетронутым ),#OPAQUE(сначала красит ячейку текста текущим цветом фона)пока так ;ikrangadgeta\Fon=CreateSolidBrush_($00FFFFFF);фон экрана по умолчанию ;ikrangadgeta\ControlFon=CreateSolidBrush_($3DFFFC);фон контролов ;ikrangadgeta\Shrift=CreateFont_(24,0,0,0,0,0,0,0,#RUSSIAN_CHARSET,0,0,#CLEARTYPE_QUALITY,0,"Lucida Console");создаем логический шрифт по умолчанию ;If ikrangadgeta\Shrift=0;дескриптор не получен(Шрифт не создан) ; HandleError(0,"Невозможно создать шрифт для CustomEditora") ; Goto NOSHRIFT ;Else ; SelectObject_(ikrangadgeta\HDC,ikrangadgeta\Shrift);установить шрифт в контекст окна рисования текста ;EndIf ;SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE)|#WS_EX_COMPOSITED) ; Rodnoy_calbak= GetWindowLongPtr_(WindowID(0), #GWL_WNDPROC) ;SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, @Window_calbak());назначаем свой обработчик Rodnoy_calbak= GetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC) SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC,@Canvas_calbak());назначаем свой обработчик Case #WM_ERASEBKGND;при заполнении окна цветом фона ;Debug 66666 ; FillRect_(ikrangadgeta\HDC,@ikrangadgeta\koordinatyikrana,ikrangadgeta\Fon) Case #WM_PAINT ; Debug 44 vyvodcontrola(0) Case #WM_MOUSEMOVE If a=1 ;Debug wparam move(2) EndIf ;Case #WM_LBUTTONDBLCLK ;control(0)\status=1 Case #WM_LBUTTONDOWN Debug hwnd move(1) a=1 Case #WM_LBUTTONUP move(0) a=0 Case #WM_RBUTTONDOWN move(3) Case #WM_CLOSE CloseWindow_(GadgetID(0)) CloseWindow_(GadgetID(1)) Case #WM_DESTROY DeleteObject_(ikrangadgeta\Fon) DeleteObject_(ikrangadgeta\ControlFon) DeleteObject_(ikrangadgeta\Shrift);Освободить дескриптор обычного печатного шрифта ReleaseDC_(GadgetID(1),ikrangadgeta\HDC) DestroyWindow_(GadgetID(0)) DestroyWindow_(GadgetID(1)) EndSelect ProcedureReturn Rezultat EndProcedure Procedure formy(fr.a) Protected a.a For a=0 To 1 If IsWindow(a) CloseWindow(a) EndIf Next If fr=0 If OpenWindow(0, 50, 0, 1200, 600, "") SmartWindowRefresh(0, #True); Уменьшаем мерцания окна при изменении его размеров HideWindow(0,1);Окно пока не отображается(закрыто) и типа все элементы на нём (гаджеты) создаются в фоновом режиме PanelGadget(990,0,25,1200,530);1-я панель AddGadgetItem(990, -1, "Бyyyy") ; ScrollAreaGadget(0, 0, 0, 1193,504,5000,5000,100) SetGadgetAttribute(0, #PB_ScrollArea_X ,2500);установка ползунка по х CanvasGadget(1, 0, 0,5000,5000,#PB_Screen_SmartSynchronization) GetClientRect_(GadgetID(1),@ikrangadgeta\koordinatyikrana);запишем полученные координаты экрана ikrangadgeta\HDC=GetDC_(GadgetID(1));запишим контекст рисования ;ikrangadgeta\HDC=GetDCEx_(GadgetID(1),0,#DCX_CACHE|#DCX_CLIPCHILDREN|#DCX_CLIPSIBLINGS);контекст с исключением дочерних окон SetBkMode_(ikrangadgeta\HDC,#TRANSPARENT);#TRANSPARENT(цвет фона прозрачный,остается нетронутым ),#OPAQUE(сначала красит ячейку текста текущим цветом фона)пока так ikrangadgeta\Fon=CreateSolidBrush_($00FFFFFF);фон экрана по умолчанию ikrangadgeta\ControlFon=CreateSolidBrush_($3DFFFC);фон контролов ikrangadgeta\Shrift=CreateFont_(24,0,0,0,0,0,0,0,#RUSSIAN_CHARSET,0,0,#CLEARTYPE_QUALITY,0,"Lucida Console");создаем логический шрифт по умолчанию If ikrangadgeta\Shrift=0;дескриптор не получен(Шрифт не создан) HandleError(0,"Невозможно создать шрифт для Панели Блок схема") ; Goto NOSHRIFT Else SelectObject_(ikrangadgeta\HDC,ikrangadgeta\Shrift);установить шрифт в контекст окна рисования текста EndIf Canvas_calbak(0,#WM_CREATE,0,0) Static s.s{10} For i=0 To 1000 Customgadget(i,i*100,i*25,100,25,"privet") Next HideWindow(0,0) ; EndIf EndIf EndProcedure formy(0) Repeat Select WaitWindowEvent() Case #PB_Event_CloseWindow Break EndSelect ForEver End
Отредактировано Sergeihik (01.11.2022 00:33:46)
Код:; Отвечает, включён ли отладчик Procedure IsDebuggerEnabled() !if defined _PB_DEBUGGER_Control !mov eax, 1 !else !mov eax, 0 !end if ProcedureReturn EndProcedure
Почему не #PB_Compiler_Debugger?
Не знаю, использует ли здесь кто-либо, методы поиска решений в подсознании. Когда ответы можно находить в пограничном состоянии, между сном и не сном. Я иногда использую.
у меня это как то само собой получается, ни чего не включаю, проблема сама по себе крутится
Способов оптимизации может быть много.
Можно запоминать текущий элемент списка и при следующей проверке начинать с него. Если курсор не выйдет за пределы элемента, не потребуется поиск в списке.
Можно изменить структуру на
Structure PosY y.i h.i name.s EndStructure Structure PosX x.i w.i List y.PosY() EndStructure
Если данные координат хранить в отсортированном виде (меньшие значения в начале, а больше в конце или наоборот). Если элемент со значением X больше чем нужно, можно прервать поиск. Аналогично с Y. Это ускорит поиск.
Список может быть очень большой.
Что в вашем понимании "ОЧЕНЬ"?
Если речь о экранных координатах, то современный комп в состоянии хранить инфу принадлежности к "объектам" каждого пикселя.
Т.е. основная нагрузка алгоритма на запоминание положения при формировании, а не на последующий поиск.
Отредактировано useful (04.11.2022 08:38:21)
EnableExplicit Define ScrW.i = 800 Define ScrH.i = 600 Define NObj = 1 Define Bw = 20 Define Bh = 20 Define Event,x,y,i,j Dim Scr.i(ScrW,ScrH) ;Массив соответствия пикселя номеру объекта OpenWindow(0,0,0,ScrW,ScrH,"",#PB_Window_MinimizeGadget | #PB_Window_ScreenCentered) CanvasGadget(0,0,0,ScrW,ScrH) Repeat Event = WaitWindowEvent() If Event = #PB_Event_Gadget And EventGadget() = 0 If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton) If StartDrawing(CanvasOutput(0)) x = GetGadgetAttribute(0, #PB_Canvas_MouseX) y = GetGadgetAttribute(0, #PB_Canvas_MouseY) Box(x, y, Bw, Bh, RGB(Random(255), Random(255), Random(255))) StopDrawing() ; ; в этом месте нужно заполнять фрагмент массива Scr (x, y, Bw, Bh) значением Nobj(номер объекта) с контролем выхода за границы ; лень думать, box() то нарисует фрагмент, какой сможет :) ; если нужно хранить слои, то наверно массив Scr превратится например в массив списков и там порядок номеров объектов на усмотрение ; Nobj + 1 EndIf EndIf EndIf Until Event = #PB_Event_CloseWindow ;На каждом этапе, по мере движения мыши мы получаем массив соответствие пикселя номеру объекта верхнего слоя ;И в последующем отпадает необходимость поиска ;Допускаю, что я не понял задачу
Отредактировано useful (05.11.2022 11:38:55)
Если это тупо объёкты в виде прямоугольника то можно взять множество канвасов (как объектов)и обработчиком определить его местоположение,это будет наверное самый быстрый способ.Если что то другое то перебор наверно надо,тогда цикл нужно делать на сопроцессоре.....
* Время на создание объектов.
Я же совсем не знаю цель происходящего.
Но ещё с времён(80-е прошлого века) дефицита как ресурсов, так и быстродействия, прежде всего думаю на тему того, что можно сделать( по считать, сформировать, ...) заранее, что бы в процессе работали автоматы (взять результат по индексу) и возможно каскадные.
Но, пока-что самым быстрым у меня остаётся перебор всех элементов списка.
Если это не пара десятков элементов, то перебор выбросить точно сразу и на всегда.
Смотреть в сторону всяких бинарных поисков и прочего или просто sqlite в памяти и заранее препарированный поисковый запрос в таблицу из 5 полей x1,x2,y1,y2,n_obj, где все поля проиндексированы конечно.
http://www.minimdb.com/mbook/mbook.html
стр. 227 гл.3 Индексация данных
Субд конечно своеобразная но глава очень полезная для общей теории.
Отредактировано useful (09.11.2022 09:38:58)
что встроенные средства в PB, для работы с БД
Причем тут PB?
Sqlite не Фред придумал, им пользуются практически поголовно самые авторитетные компании мира.
За двадцать с лишним лет код вылизан до блеска.
https://www.sqlite.org/inmemorydb.html
100 тыс. объектов на поле 5000*5000
На моём холодном целероне j1800 стабильно 15-20 миллисекунд и это грубый набросок без каких бы то ни было попыток оптимизации.
Причём в примере вытаскиваются все найденные. Короче есть куда развиваться.
p.s. а оговоренные ранее 65000 - 5-10 миллисекунд.
==============
p.p.s. Ну а с числами
W = 900 ; Ширина поля
H = 600 ; Высота поля
O = 3899 ; Количество оъектов
Выйти за пределы НУЛЯ миллисекунд я так и не смог!!!!!!!!!
==============
UseSQLiteDatabase() Procedure CheckDatabaseUpdate(Database, Query$) ;DatabaseUpdate(Database, "BEGIN TRANSACTION;") Result = DatabaseUpdate(Database, Query$) If Result = 0 Debug DatabaseError() EndIf ;DatabaseUpdate(Database, "END TRANSACTION;") ProcedureReturn Result EndProcedure W = 5000 ; Ширина поля H = 5000 ; Высота поля O = 100000 ; Количество оъектов If OpenDatabase(0, ":memory:", "", "") CheckDatabaseUpdate(0, "CREATE TABLE tObject (NObject INT, X1 INT, Y1 INT, X2 INT, Y2 INT)") CheckDatabaseUpdate(0, "CREATE INDEX iObject ON tObject (NObject, X1, Y1, X2, Y2)") For i = 1 To O Ow = Random(100,10) Oh = Random(100,10) Ox = Random(W-Ow,0) Oy = Random(H-Oh,0) Req1.s = "INSERT INTO tObject (NObject,X1, Y1, X2, Y2) VALUES (" Req2.s = Str(i) + "," Req2.s = Req2 + Str(Ox) + "," Req2.s = Req2 + Str(Oy) + "," Req2.s = Req2 + Str(Ox+Ow-1) + "," Req2.s = Req2 + Str(Oy+Oh-1) + ")" CheckDatabaseUpdate(0, Req1+Req2) Next x = Random(W-1,0) y = Random(H-1,0) SetDatabaseLong(0,0,x) SetDatabaseLong(0,1,x) SetDatabaseLong(0,2,y) SetDatabaseLong(0,3,y) L = 0 StartTime.q = ElapsedMilliseconds() If DatabaseQuery(0, "SELECT NObject FROM tObject WHERE (X1 <= ?) AND (X2 >= ?) AND (Y1 <= ?) AND (Y2 >= ?) ORDER BY NObject ") While NextDatabaseRow(0) L = GetDatabaseLong(0, 0) Wend FinishDatabaseQuery(0) EndIf ;Debug "====" MessageRequester("Information", Str(L) + "=" + Str( ElapsedMilliseconds() - StartTime), #PB_MessageRequester_Ok | #PB_MessageRequester_Info) ;ElapsedMilliseconds() - StartTime CloseDatabase(0) Else Debug "Can't open database !" EndIf
Отредактировано useful (10.11.2022 09:25:35)
Структура координат в массиве должна быть отдельно а строка вынесенна в отдельный массив
Потому как она имеет переменную длину.
Либо использовать для неё переменную ссылки на выделенную память(если динамически)
Либо на статическую датасекцию
Возможно пурик в массив (память)с типом строки
и ложит как ссылку?(надо проверять)
Тогда можно и в структуру определить.
Structure koordinaty X.i Yi X1.i Y1.i Endstructure Global count.i Global dim koordinary.koordinaty(100000) Global dim Stroka.s(100000) Procedure Set_object() Protected i.i count=100000 For i=0 to count koordinaty(i)\X=i koordinaty(i)\X1=i+100 koordinaty(i)\Y=i koordinaty(i)\Y1=i+100 Stroka(i)="Stroka" Next Endprocedure Procedure poisk(*massiv,x,y,count);для теста Count*16 !xor ecx,ecx !mov dword ebx,[p.v_x] !mov dword edx,[p.v_y] !mov dword eax,[p.p_massiv] !cikl: !cmp dword ebx,[eax+ecx] !ja xbolhe;x>koor\x !cmp dword ecx,[p.v_Count] !jz vyhod !add dword ecx,16 !jmp cikl !xbolhe: !cmp dword ebx,[eax+ecx+8] ijl xmenhe;x<koor\x1 !cmp dword ecx,[p.v_Count] !jz vyhod !add dword ecx,16 !xmenhe:;x мы между kor\x <x> kor\x1 ; !cmp dword edx,[eax+ecx+4] !ybolhe; kor\y<y !cmp dword ecx,[p.v_Count] !jz vyhod !ybolhe: !vyhod:не найдено Procedurereturn -1 Endprocedure
Ps:приду домой подправлю допишу тест
Отредактировано Sergeihik (10.11.2022 15:42:45)
ДА на асме нужно переделывать доделывать зделал и удалил
оказалось что переменную count глобальную компилятор путал с count в процедуре.....
и не работало как на асме так и в этом коде,пришлось имя поменять.
причём тут
Procedure Set_object(count1) ReDim koordinaty.koordinaty(count1) ReDim Stroka.s(count1)
сделал так заработало
Structure koordinaty X.i Y.i X1.i Y1.i EndStructure Global count.i Global Dim koordinaty.koordinaty(0) Global Dim Stroka.s(0) Procedure Set_object(count1) ReDim koordinaty.koordinaty(count1) ReDim Stroka.s(count1) Protected i.i count=count1 For i=0 To count koordinaty(i)\X=i koordinaty(i)\X1=i+100 koordinaty(i)\Y=i koordinaty(i)\Y1=i+100 Stroka(i)=Str(i) Next EndProcedure Procedure.i poisk(*massiv.koordinaty,x,y,countt);для теста Protected r.i=*massiv countt*16 countt+*massiv cikl: If x>*massiv\X And x<*massiv\X1 And y>*massiv\Y And y<*massiv\Y1 *massiv-r *massiv/16 ProcedureReturn *massiv Else If *massiv<>countt *massiv+16 Goto cikl Else ProcedureReturn -1 EndIf EndIf EndProcedure Set_object(1000000) TimeS.q = ElapsedMilliseconds() index.l= poisk(@koordinaty(),count+50,count+50,count) ArrTime.q = ElapsedMilliseconds() - TimeS MessageRequester("Тест","index "+Str(index)+" stroka "+Stroka.s(index)+" время теста "+Str(ArrTime))
Отредактировано Sergeihik (10.11.2022 19:39:19)
Более правильно сделал.
Ps:Ну да перебор от начала массива,да на асме проц так негрузится почему то у меня.
Ну и делать счёт count от 0 или 1 чтобы в процедурах поиска учесть этот момент (но это думаю не критично так как поиск основной в сравнении)
Structure koordinaty X.i Y.i X1.i Y1.i EndStructure Global count.i Global Dim koordinaty.koordinaty(0) Global Dim Stroka.s(0) Procedure Set_object(count1) ReDim koordinaty.koordinaty(count1-1) ReDim Stroka.s(count1-1) Protected i.i count=count1 For i=0 To count-1 koordinaty(i)\X=i koordinaty(i)\X1=i+100 koordinaty(i)\Y=i koordinaty(i)\Y1=i+100 Stroka(i)=Str(i) Next EndProcedure Procedure poisk(x,y) If count>0 For i=0 To count-1 With koordinaty(i) If x>=\X And x<=\X1 And y>=\Y And y<=\Y1 ProcedureReturn i EndIf EndWith Next ProcedureReturn -1 EndIf EndProcedure Procedure.i poisk2(*massiv.koordinaty,x,y,size);для теста If size<1 ProcedureReturn -1 EndIf Protected r.i=*massiv size*16 size+*massiv cikl: If x>*massiv\X And x<*massiv\X1 And y>*massiv\Y And y<*massiv\Y1 *massiv-r If *massiv=0 ProcedureReturn *massiv Else *massiv/16 ProcedureReturn *massiv;index массива с 0 EndIf Else *massiv+16 If *massiv<>size Goto cikl EndIf ProcedureReturn -1 EndIf EndProcedure Procedure.i poisk3(*massiv,x,y,countt);для теста !cmp dword [p.v_countt],0 !jz vyhod5 ; !mov dword eax,[p.p_massiv] !sal dword [p.v_countt],4 !add dword [p.v_countt],eax !mov dword ebx,[p.v_x] !mov dword edx,[p.v_y] !jmp r4555 !ckl777: !add dword eax,16 !cmp dword eax,[p.v_countt] !jz vyhod5 !r4555: !cmp dword ebx,[eax] !jl ckl777 !cmp dword ebx,[eax+8] !jg ckl777 !cmp dword edx,[eax+4] !jl ckl777 !cmp dword edx,[eax+12] !jg ckl777 !sub dword eax,[p.p_massiv] !cmp dword eax,0 !jz f6544 !sar dword eax,4 !f6544: ProcedureReturn !vyhod5: ProcedureReturn -1 EndProcedure Procedure.i poisk4(*massiv,x,y,countt);для теста !mov dword ecx,[p.p_massiv] !xor eax,eax !mov dword ebx,[p.v_x] !mov dword edx,[p.v_y] !jmp g8677 !vyhod134: ProcedureReturn -1 !ckl655: ;!add dword eax,1 !inc eax !cmp dword eax,[p.v_countt] !jz vyhod134 !add dword ecx,16 !g8677: ; !cmp dword ebx,dword[ecx] !jl ckl655 !cmp dword ebx,[ecx+8] !jg ckl655 !cmp dword edx,[ecx+4] !jl ckl655 !cmp dword edx,[ecx+12] !jg ckl655 ; ProcedureReturn EndProcedure Set_object(10000000) ;Тест 1 TimeS.q = ElapsedMilliseconds() index.l= poisk(count+50,count+50) ArrTime.q = ElapsedMilliseconds() - TimeS MessageRequester("Тест","index "+Str(index)+" stroka "+Stroka.s(index)+" время теста "+Str(ArrTime)) ;Тест 2 TimeS.q = ElapsedMilliseconds() index= poisk2(@koordinaty(),count+50,count+50,count) ArrTime.q = ElapsedMilliseconds() - TimeS MessageRequester("Тест","index "+Str(index)+" stroka "+Stroka.s(index)+" время теста "+Str(ArrTime)) ;Тест 3 TimeS.q = ElapsedMilliseconds() index= poisk3(@koordinaty(),count+50,count+50,count) ArrTime.q = ElapsedMilliseconds() - TimeS MessageRequester("Тест","index "+Str(index)+" stroka "+Stroka.s(index)+" время теста "+Str(ArrTime)) ;Тест 4 TimeS.q = ElapsedMilliseconds() index= poisk4(@koordinaty(),count+50,count+50,count) ArrTime.q = ElapsedMilliseconds() - TimeS MessageRequester("Тест","index "+Str(index)+" stroka "+Stroka.s(index)+" время теста "+Str(ArrTime))
Отредактировано Sergeihik (11.11.2022 10:36:57)
А какие алгоритмы кроме перебора?
Если вы ищете с конца и начала к середине то смысла нет,тот же перебор только инструкций больше процессору= меньше скоростть(пока дойдёшь до середины всё равно просканируешь весь массив<тоесть участок середины = участку конца поиска с начала)
Тогда уж проще разделить массив на попалам и в двух патоках поиск делать, но при 10000 тысячах стоит оно того?
Ну какой встречный поиск без потоков ,ну сделай тест поиска на середине(координата,если поиск к середине) и посмотри как это скажется!
можно и рандом сделать но опять же замедлит это всё!
PS; вижу только на сопроцессоре увеличение скорости,но примеры надо искать(забыл нахрен)но подвигло это всё к написанию шпаргалки по асму,ну давно хотел(насколько интузиазма хватит?)
Для x64 как то так регистры адресации 64 бита
Ну и метки поменять на другие
Procedure.i poisk3(*massiv,x,y,countt);для теста CompilerIf #PB_Compiler_Processor = #PB_Processor_x64 ;{; !cmp qword [p.v_countt],0 !jz vyhod56 ; !mov qword rax,[p.p_massiv];64 битта стек и наш countt можно(поменять на тип Global count.q) !sal qword [p.v_countt],4 !add qword [p.v_countt],rax !mov dword ebx,[p.v_x];как интегер 32бит(может быстрей поиск будет да и массив x,y.интегер) !mov dword edx,[p.v_y]; !jmp r45556 !ckl7774: !add qword rax,16 !cmp qword rax,[p.v_countt] !jz vyhod5 !r45556: !cmp dword ebx,[rax] !jl ckl7774 !cmp dword ebx,[rax+8] !jg ckl7774 !cmp dword edx,[rax+4] !jl ckl7774 !cmp dword edx,[rax+12] !jg ckl7774 !sub qword rax,[p.p_massiv] !cmp qword rax,0 !jz f65447 !sar qword rax,4 !f65447: ProcedureReturn !vyhod56: ProcedureReturn -1 ;}; CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x86 ;{; !cmp dword [p.v_countt],0 !jz vyhod5 ; !mov dword eax,[p.p_massiv] !sal dword [p.v_countt],4 !add dword [p.v_countt],eax !mov dword ebx,[p.v_x] !mov dword edx,[p.v_y] !jmp r4555 !ckl777: !add dword eax,16 !cmp dword eax,[p.v_countt] !jz vyhod5 !r4555: !cmp dword ebx,[eax] !jl ckl777 !cmp dword ebx,[eax+8] !jg ckl777 !cmp dword edx,[eax+4] !jl ckl777 !cmp dword edx,[eax+12] !jg ckl777 !sub dword eax,[p.p_massiv] !cmp dword eax,0 !jz f6544 !sar dword eax,4 !f6544: ProcedureReturn !vyhod5: ProcedureReturn -1 ;}; CompilerEndIf EndProcedure
Отредактировано Sergeihik (13.11.2022 12:35:24)
Вот пример попробоал но тормозит жуть....
Procedure.i poisk5(*massiv,x,y,countt);для теста Protected adres_1.i=1;для сложения !cmp dword [p.v_countt],0 !jz vuhod543 !sub dword ptr p.v_countt,1;countt-1 !mov dword eax,[p.p_massiv] ; !XORPS xmm0,xmm0;обнулим xmm0 ;!movss xmm1,dword ptr p.v_adres_1;xmm1=1,младший регистр[32 bit] остальные 96 бит=0 !movss xmm2,dword ptr p.v_x;загружает значение с плавающей запятой у нас как бы целое число !movss xmm3,dword ptr p.v_y !jmp ryrr43 !cikl74356: !addss xmm0,dword ptr p.v_adres_1;xmm0+1 ;!addss xmm0,xmm1;xmm0+1 ; !comiss xmm0,[p.v_countt];Скалярное сравнение с установкой eflags !jz vuhod543 !add eax,16 ; !ryrr43: !comiss xmm2,[eax] !jl cikl74356 !comiss xmm3,[eax+8] !jg cikl74356 !comiss xmm2,[eax+4] !jl cikl74356 !comiss xmm3,[eax+12] !jg cikl74356 ;ок нашли !movss dword [p.v_adres_1],xmm0;запишем индекс поиска ProcedureReturn adres_1 !vuhod543: ProcedureReturn -1 EndProcedure
Вообще бинарный поиск очень ускоряет - но время на вставку увеличивается, так как надо отсортировывать массив/список
Ну так с последнего и ищите тогда,зачем первые смотреть вдруг следующий ближе к верху искомый?
Не два элемента же а сотни ,миллионы...........
Procedure.i Pt_Vmassive_Rect(*rect,x,y,countt) !push ebp !mov ebp,esp !mov eax,[ebp+8] !test eax,eax;есть адрес ? !jz trghh;типа нет выходим !cmp dword [ebp+20],0 !jz trghh;типа countt=0 !sal dword [ebp+20],4;countt*16 ;!add dword [ebp+20],eax;поиск с начала !add dword eax,[ebp+20];поиск с конца ; !mov ecx,[ebp+12];ecx=x !mov ebx,[ebp+16];ecx=y !jmp trrty !cikl8655: ;!add dword eax,16;;поиск с начала ;!cmp dword eax,[ebp+20];поиск с начала !cmp dword eax,[ebp+8];=адресу *rect ? !jz trghh !trrty: !sub dword eax,16;поиск с конца предварительно отнимем вначале цикла адрес -16 count=1 adres =+16 !cmp ecx,[eax];x<*rect\x !jl cikl8655 !cmp ecx,[eax+8];x>=*rect\x1 !jg cikl8655 !cmp ebx,[eax+4];y<*rect\y !jl cikl8655 !cmp ebx,[eax+12];y>*rect\y1 !jg cikl8655 ; !sub dword eax,[ebp+8];текущий адрес eax минус начальный *rect !jz gffgh;eax=0;если count=1 один элемент рамки то будет 0 !sar dword eax,4;если больше то делим значение на 16 адресация массива рамок по 16 байт !gffgh: !pop ebp ProcedureReturn ;результат поиска возвращается в eax !trghh: !pop ebp ProcedureReturn -1 EndProcedure
Отредактировано Sergeihik (14.11.2022 02:05:06)
Это чегойто меня гонишь?
У меня вопрос вот наводящий а для чего вы в примере разноцветные объекты рисуете?
Sergeihik, не нужно игнорировать просьбу автора темы.
Sergeihik, не нужно игнорировать просьбу автора темы.
Ок покидаю ветку,я про цвет к тому что это тоже может быть идинтификатором к поиску,к примеру 10цветов на 10груп объектов соответственно прирост поиск под 10раз!
Да и тему он толком не раскрыл про нижний верхний,так как менять координаты собрался соответственно этот верхний допустим станет нижним или средним?
Ну да ладно дальше пусть другие думают.
Отредактировано Sergeihik (14.11.2022 13:07:29)
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.