PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.


Быстрый способ найти в списке прямоугольник, по координате.

Сообщений 1 страница 24 из 24

1

gjrbyek ajhev

Отредактировано Webarion (13.06.2025 13:07:53)

0

2

Что то подобное мутил,только в массиве

Код:

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)

+1

3

Webarion написал(а):
Код:
; Отвечает, включён ли отладчик
Procedure IsDebuggerEnabled()
  !if defined _PB_DEBUGGER_Control
  !mov eax, 1
  !else
  !mov eax, 0
  !end if
  ProcedureReturn
EndProcedure

Почему не #PB_Compiler_Debugger?

+1

4

Webarion написал(а):

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

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

0

5

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

Код:
Structure PosY
  y.i
  h.i
  name.s
EndStructure

Structure PosX
  x.i
  w.i
  List y.PosY()
EndStructure

Если данные координат хранить в отсортированном виде (меньшие значения в начале, а больше в конце или наоборот). Если элемент со значением X больше чем нужно, можно прервать поиск. Аналогично с Y. Это ускорит поиск.

+1

6

Webarion написал(а):

Список может быть очень большой.

Что в вашем понимании "ОЧЕНЬ"?
Если речь о экранных координатах, то современный комп в состоянии хранить инфу принадлежности к "объектам" каждого пикселя.
Т.е. основная нагрузка алгоритма на запоминание положения при формировании, а не на последующий поиск.

Отредактировано useful (04.11.2022 08:38:21)

0

7

Код:
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)

0

8

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

0

9

Webarion написал(а):

* Время на создание объектов.

Я же совсем не знаю цель происходящего.
Но ещё с времён(80-е прошлого века) дефицита как ресурсов, так и быстродействия, прежде всего думаю на тему того, что можно сделать( по считать, сформировать, ...) заранее, что бы в процессе работали автоматы (взять результат по индексу) и возможно каскадные.

0

10

Webarion написал(а):

Но, пока-что самым быстрым у меня остаётся перебор всех элементов списка.

Если это не пара десятков элементов, то перебор выбросить точно сразу и на всегда.
Смотреть в сторону всяких бинарных поисков и прочего или просто sqlite в памяти и заранее препарированный поисковый запрос в таблицу из 5 полей x1,x2,y1,y2,n_obj, где все поля проиндексированы конечно.

http://www.minimdb.com/mbook/mbook.html
стр. 227 гл.3 Индексация данных
Субд конечно своеобразная но глава очень полезная для общей теории.

Отредактировано useful (09.11.2022 09:38:58)

+1

11

Webarion написал(а):

что встроенные средства в PB, для работы с БД

Причем тут PB?
Sqlite не Фред придумал, им пользуются практически поголовно самые авторитетные компании мира.
За двадцать с лишним лет код вылизан до блеска.
https://www.sqlite.org/inmemorydb.html

0

12

100 тыс. объектов на поле 5000*5000
На моём холодном целероне j1800 стабильно 15-20 миллисекунд и это грубый набросок без каких бы то ни было попыток оптимизации.
Причём в примере вытаскиваются все найденные. Короче есть куда развиваться.
p.s. а оговоренные ранее 65000 - 5-10 миллисекунд.
==============
p.p.s. Ну а с числами
W = 900 ; Ширина поля
H = 600 ; Высота поля
O = 3899 ; Количество оъектов
Выйти за пределы НУЛЯ миллисекунд я так и не смог!!!!!!!!!  :dontknow:
==============

Код:
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)

0

13

Структура координат в массиве должна быть отдельно а строка вынесенна в отдельный массив
Потому как она имеет переменную длину.
Либо использовать для неё переменную ссылки на выделенную память(если динамически)
Либо на статическую датасекцию
Возможно пурик в массив (память)с типом строки
и ложит как ссылку?(надо проверять)
Тогда можно и в структуру определить.

Код:
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)

0

14

ДА на асме нужно переделывать доделывать зделал и удалил
оказалось что  переменную 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)

0

15

Более правильно сделал.
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)

+1

16

А какие алгоритмы кроме перебора?
Если вы ищете с конца и начала к середине то смысла нет,тот же перебор только инструкций больше процессору= меньше скоростть(пока дойдёшь до середины всё равно просканируешь весь массив<тоесть участок середины = участку конца поиска с начала)
Тогда уж проще разделить массив на попалам и в двух патоках поиск делать, но при 10000 тысячах стоит оно того?

0

17

Ну какой встречный поиск без потоков ,ну сделай тест поиска на середине(координата,если поиск к середине) и посмотри как это скажется!
можно и рандом сделать но опять же замедлит это всё!
PS; вижу только на сопроцессоре увеличение скорости,но примеры надо искать(забыл нахрен)но подвигло это всё к написанию шпаргалки по асму,ну давно хотел(насколько интузиазма хватит?)

0

18

Для 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)

0

19

Вот пример попробоал но тормозит жуть....

Код:
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

0

20

Вообще бинарный поиск очень ускоряет - но время на вставку увеличивается, так как надо отсортировывать массив/список

0

21

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

Код:
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)

-1

22

Это чегойто меня гонишь?
У меня вопрос вот наводящий а для чего вы в примере разноцветные объекты рисуете?

0

23

Sergeihik, не нужно игнорировать просьбу автора темы.

0

24

Пётр написал(а):

Sergeihik, не нужно игнорировать просьбу автора темы.

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

Отредактировано Sergeihik (14.11.2022 13:07:29)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.