GLS.VectorLists.pas 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397
  1. //
  2. // The graphics rendering engine GLScene http://glscene.org
  3. //
  4. unit GLS.VectorLists;
  5. (* Misc. lists of vectors and entities *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. GLS.VectorTypes,
  12. GLS.VectorGeometry,
  13. GLS.PersistentClasses;
  14. type
  15. TBaseListOption = (bloExternalMemory, bloSetCountResetsMemory);
  16. TBaseListOptions = set of TBaseListOption;
  17. // Base class for lists, introduces common behaviours
  18. TBaseList = class(TPersistentObject)
  19. private
  20. FCount: Integer;
  21. FCapacity: Integer;
  22. FGrowthDelta: Integer;
  23. FBufferItem: PByteArray;
  24. FOptions: TBaseListOptions;
  25. FRevision: LongWord;
  26. FTagString: string;
  27. protected
  28. // The base list pointer (untyped)
  29. FBaseList: PByteArray;
  30. // Must be defined by all subclasses in their constructor(s)
  31. FItemSize: Integer;
  32. procedure SetCount(Val: Integer); inline;
  33. (* Only function where list may be alloc'ed & freed.
  34. Resizes the array pointed by FBaseList, adjust the subclass's
  35. typed pointer accordingly if any *)
  36. procedure SetCapacity(NewCapacity: Integer); virtual;
  37. function BufferItem: PByteArray; inline;
  38. function GetSetCountResetsMemory: Boolean; inline;
  39. procedure SetSetCountResetsMemory(const Val: Boolean);
  40. // Borland-style persistency support.
  41. procedure ReadItemsData(AReader : TReader); virtual;
  42. procedure WriteItemsData(AWriter : TWriter); virtual;
  43. procedure DefineProperties(AFiler: TFiler); override;
  44. public
  45. constructor Create; override;
  46. destructor Destroy; override;
  47. procedure Assign(Src: TPersistent); override;
  48. procedure WriteToFiler(writer: TVirtualWriter); override;
  49. procedure ReadFromFiler(reader: TVirtualReader); override;
  50. procedure AddNulls(nbVals: Cardinal);
  51. procedure InsertNulls(Index: Integer; nbVals: Cardinal);
  52. procedure AdjustCapacityToAtLeast(const size: Integer);
  53. function DataSize: Integer;
  54. (*Tell the list to use the specified range instead of its own.
  55. rangeCapacity should be expressed in bytes.
  56. The allocated memory is NOT managed by the list, current content
  57. if copied to the location, if the capacity is later changed, regular
  58. memory will be allocated, and the specified range no longer used *)
  59. procedure UseMemory(rangeStart: Pointer; rangeCapacity: Integer);
  60. // Empties the list without altering capacity
  61. procedure Flush; inline;
  62. // Empties the list and release
  63. procedure Clear;
  64. procedure Delete(Index: Integer);
  65. procedure DeleteItems(Index: Integer; nbVals: Cardinal);
  66. procedure Exchange(index1, index2: Integer); inline;
  67. procedure Move(curIndex, newIndex: Integer); inline;
  68. procedure Reverse;
  69. // Nb of items in the list. When assigning a Count, added items are reset to zero
  70. property Count: Integer read FCount write SetCount;
  71. // Current list capacity. Not persistent
  72. property Capacity: Integer read FCapacity write SetCapacity;
  73. // List growth granularity. Not persistent
  74. property GrowthDelta: Integer read FGrowthDelta write FGrowthDelta;
  75. (* If true (default value) adjusting count will reset added values.
  76. Switching this option to true will turn off this memory reset,
  77. which can improve performance is that having empty values isn't required. *)
  78. property SetCountResetsMemory: Boolean read GetSetCountResetsMemory write SetSetCountResetsMemory;
  79. property TagString: string read FTagString write FTagString;
  80. // Increase by one after every content changes
  81. property Revision: LongWord read FRevision write FRevision;
  82. end;
  83. // Base class for vector lists, introduces common behaviours
  84. TBaseVectorList = class(TBaseList)
  85. protected
  86. function GetItemAddress(Index: Integer): PFloatArray; inline;
  87. public
  88. procedure WriteToFiler(writer: TVirtualWriter); override;
  89. procedure ReadFromFiler(reader: TVirtualReader); override;
  90. procedure GetExtents(out min, max: TAffineVector); virtual;
  91. function Sum: TAffineVector;
  92. procedure Normalize; virtual;
  93. function MaxSpacing(list2: TBaseVectorList): Single;
  94. procedure Translate(const delta: TAffineVector); overload; virtual;
  95. procedure Translate(const delta: TBaseVectorList); overload; virtual;
  96. procedure TranslateInv(const delta: TBaseVectorList); overload; virtual;
  97. (*Replace content of the list with lerp results between the two given lists.
  98. Note: you can't Lerp with Self!!! *)
  99. procedure Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single); virtual; abstract;
  100. (* Replace content of the list with angle lerp between the two given lists.
  101. Note: you can't Lerp with Self!!! *)
  102. procedure AngleLerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  103. procedure AngleCombine(const list1: TBaseVectorList; intensity: Single);
  104. //Linear combination of Self with another list. Self[i]:=Self[i]+list2[i]*factor
  105. procedure Combine(const list2: TBaseVectorList; factor: Single); virtual;
  106. property ItemAddress[Index: Integer]: PFloatArray read GetItemAddress;
  107. end;
  108. (*A list of TAffineVector.
  109. Similar to TList, but using TAffineVector as items.
  110. The list has stack-like push/pop methods *)
  111. TAffineVectorList = class(TBaseVectorList)
  112. private
  113. FList: PAffineVectorArray;
  114. protected
  115. function Get(Index: Integer): TAffineVector; inline;
  116. procedure Put(Index: Integer; const item: TAffineVector); inline;
  117. procedure SetCapacity(NewCapacity: Integer); override;
  118. public
  119. constructor Create; override;
  120. procedure Assign(Src: TPersistent); override;
  121. function Add(const item: TAffineVector): Integer; overload;
  122. function Add(const item: TGLVector): Integer; overload;
  123. procedure Add(const i1, i2: TAffineVector); overload;
  124. procedure Add(const i1, i2, i3: TAffineVector); overload;
  125. function Add(const item: TVector2f): Integer; overload;
  126. function Add(const item: TTexPoint): Integer; overload;
  127. function Add(const X, Y: Single): Integer; overload;
  128. function Add(const X, Y, Z: Single): Integer; overload;
  129. function Add(const X, Y, Z: Integer): Integer; overload;
  130. // Add (3 ints, no capacity check)
  131. function AddNC(const X, Y, Z: Integer): Integer; overload;
  132. // Add (2 ints in array + 1)
  133. function Add(const xy: PIntegerArray; const Z: Integer): Integer; overload;
  134. // AddNC (2 ints in array + 1, no capacity check)
  135. function AddNC(const xy: PIntegerArray; const Z: Integer): Integer; overload;
  136. procedure Add(const list: TAffineVectorList); overload;
  137. procedure Push(const Val: TAffineVector);
  138. function Pop: TAffineVector;
  139. procedure Insert(Index: Integer; const item: TAffineVector); inline;
  140. function IndexOf(const item: TAffineVector): Integer;
  141. function FindOrAdd(const item: TAffineVector): Integer;
  142. property Items[Index: Integer]: TAffineVector read Get write Put; default;
  143. property List: PAffineVectorArray read FList;
  144. procedure Translate(const delta: TAffineVector); overload; override;
  145. procedure Translate(const delta: TAffineVector; base, nb: Integer); overload;
  146. // Translates the given item
  147. procedure TranslateItem(Index: Integer; const delta: TAffineVector);
  148. // Translates given items
  149. procedure TranslateItems(Index: Integer; const delta: TAffineVector; nb: Integer);
  150. // Combines the given item
  151. procedure CombineItem(Index: Integer; const vector: TAffineVector; const f: Single);
  152. (*Transforms all items by the matrix as if they were points.
  153. ie. the translation component of the matrix is honoured. *)
  154. procedure TransformAsPoints(const matrix: TGLMatrix);
  155. (* Transforms all items by the matrix as if they were vectors.
  156. ie. the translation component of the matrix is not honoured. *)
  157. procedure TransformAsVectors(const matrix: TGLMatrix); overload;
  158. procedure TransformAsVectors(const matrix: TAffineMatrix); overload;
  159. procedure Normalize; override;
  160. procedure Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single); override;
  161. procedure Scale(factor: Single); overload;
  162. procedure Scale(const factors: TAffineVector); overload;
  163. end;
  164. (* A list of TGLVector.
  165. Similar to TList, but using TGLVector as items.
  166. The list has stack-like push/pop methods *)
  167. TVectorList = class(TBaseVectorList)
  168. private
  169. FList: PVectorArray;
  170. protected
  171. function Get(Index: Integer): TGLVector; inline;
  172. procedure Put(Index: Integer; const item: TGLVector); inline;
  173. procedure SetCapacity(NewCapacity: Integer); override;
  174. public
  175. constructor Create; override;
  176. procedure Assign(Src: TPersistent); override;
  177. function Add(const item: TGLVector): Integer; overload; inline;
  178. function Add(const item: TAffineVector; w: Single): Integer; overload; inline;
  179. function Add(const X, Y, Z, w: Single): Integer; overload; inline;
  180. procedure Add(const i1, i2, i3: TAffineVector; w: Single); overload; inline;
  181. function AddVector(const item: TAffineVector): Integer; overload;
  182. function AddPoint(const item: TAffineVector): Integer; overload;
  183. function AddPoint(const X, Y: Single; const Z: Single = 0): Integer; overload;
  184. procedure Push(const Val: TGLVector);
  185. function Pop: TGLVector;
  186. function IndexOf(const item: TGLVector): Integer;
  187. function FindOrAdd(const item: TGLVector): Integer;
  188. function FindOrAddPoint(const item: TAffineVector): Integer;
  189. procedure Insert(Index: Integer; const item: TGLVector);
  190. property Items[Index: Integer]: TGLVector read Get write Put; default;
  191. property List: PVectorArray read FList;
  192. procedure Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single); override;
  193. end;
  194. (* A list of TTexPoint.
  195. Similar to TList, but using TTexPoint as items.
  196. The list has stack-like push/pop methods. *)
  197. TTexPointList = class(TBaseVectorList)
  198. private
  199. FList: PTexPointArray;
  200. protected
  201. function Get(Index: Integer): TTexPoint;
  202. procedure Put(Index: Integer; const item: TTexPoint);
  203. procedure SetCapacity(NewCapacity: Integer); override;
  204. public
  205. constructor Create; override;
  206. procedure Assign(Src: TPersistent); override;
  207. function IndexOf(const item: TTexpoint): Integer;
  208. function FindOrAdd(const item: TTexpoint): Integer;
  209. function Add(const item: TTexPoint): Integer; overload;
  210. function Add(const item: TVector2f): Integer; overload;
  211. function Add(const texS, Text: Single): Integer; overload;
  212. function Add(const texS, Text: Integer): Integer; overload;
  213. function AddNC(const texS, Text: Integer): Integer; overload;
  214. function Add(const texST: PIntegerArray): Integer; overload;
  215. function AddNC(const texST: PIntegerArray): Integer; overload;
  216. procedure Push(const Val: TTexPoint);
  217. function Pop: TTexPoint;
  218. procedure Insert(Index: Integer; const item: TTexPoint);
  219. property Items[Index: Integer]: TTexPoint read Get write Put; default;
  220. property List: PTexPointArray read FList;
  221. procedure Translate(const delta: TTexPoint);
  222. procedure ScaleAndTranslate(const scale, delta: TTexPoint); overload;
  223. procedure ScaleAndTranslate(const scale, delta: TTexPoint; base, nb: Integer); overload;
  224. procedure Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single); override;
  225. end;
  226. (* A list of Integers.
  227. Similar to TList, but using TTexPoint as items.
  228. The list has stack-like push/pop methods. *)
  229. TIntegerList = class(TBaseList)
  230. private
  231. FList: PIntegerArray;
  232. protected
  233. function Get(Index: Integer): Integer; inline;
  234. procedure Put(Index: Integer; const item: Integer); inline;
  235. procedure SetCapacity(newCapacity: Integer); override;
  236. public
  237. constructor Create; override;
  238. procedure Assign(src: TPersistent); override;
  239. function Add(const item: Integer): Integer; overload; inline;
  240. function AddNC(const item: Integer): Integer; overload; inline;
  241. procedure Add(const i1, i2: Integer); overload; inline;
  242. procedure Add(const i1, i2, i3: Integer); overload; inline;
  243. procedure Add(const AList: TIntegerList); overload; inline;
  244. procedure Push(const Val: Integer); inline;
  245. function Pop: Integer; inline;
  246. procedure Insert(Index: Integer; const item: Integer); inline;
  247. procedure Remove(const item: Integer); inline;
  248. function IndexOf(item: Integer): Integer; inline;
  249. property Items[Index: Integer]: Integer read Get write Put; default;
  250. property List: PIntegerArray read FList;
  251. // Adds count items in an arithmetic serie. Items are (aBase),(aBase+aDelta)...(aBase+(aCount-1)*aDelta)
  252. procedure AddSerie(aBase, aDelta, aCount: Integer);
  253. // Add n integers at the address starting at (and including) first
  254. procedure AddIntegers(const First: PInteger; n: Integer); overload;
  255. // Add all integers from aList into the list
  256. procedure AddIntegers(const aList: TIntegerList); overload;
  257. // Add all integers from anArray into the list
  258. procedure AddIntegers(const anArray: array of Integer); overload;
  259. // Returns the minimum integer item, zero if list is empty
  260. function MinInteger: Integer;
  261. // Returns the maximum integer item, zero if list is empty
  262. function MaxInteger: Integer;
  263. // Sort items in ascending order
  264. procedure Sort;
  265. // Sort items in ascending order and remove duplicated integers
  266. procedure SortAndRemoveDuplicates;
  267. // Locate a value in a sorted list
  268. function BinarySearch(const Value: Integer): Integer; overload;
  269. (* Locate a value in a sorted list.
  270. If ReturnBestFit is set to true, the routine will return the position
  271. of the largest value that's smaller than the sought value. Found will
  272. be set to True if the exact value was found, False if a "BestFit" was found *)
  273. function BinarySearch(const Value: Integer; returnBestFit: Boolean; var found: Boolean): Integer; overload;
  274. (* Add integer to a sorted list.
  275. Maintains the list sorted. If you have to add "a lot" of integers
  276. at once, use the Add method then Sort the list for better performance. *)
  277. function AddSorted(const Value: Integer; const ignoreDuplicates: Boolean = False): Integer;
  278. // Removes an integer from a sorted list
  279. procedure RemoveSorted(const Value: Integer);
  280. // Adds delta to all items in the list
  281. procedure Offset(delta: Integer); overload;
  282. procedure Offset(delta: Integer; const base, nb: Integer); overload;
  283. end;
  284. TSingleArrayList = array[0..MaxInt shr 4] of Single;
  285. PSingleArrayList = ^TSingleArrayList;
  286. (* A list of Single.
  287. Similar to TList, but using Single as items.
  288. The list has stack-like push/pop methods *)
  289. TSingleList = class(TBaseList)
  290. private
  291. FList: PSingleArrayList;
  292. protected
  293. function Get(Index: Integer): Single; inline;
  294. procedure Put(Index: Integer; const item: Single); inline;
  295. procedure SetCapacity(NewCapacity: Integer); override;
  296. public
  297. constructor Create; override;
  298. procedure Assign(Src: TPersistent); override;
  299. function Add(const item: Single): Integer; overload; inline;
  300. procedure Add(const i1, i2: Single); overload; inline;
  301. procedure AddSingles(const First: PSingle; n: Integer); overload; inline;
  302. procedure AddSingles(const anArray: array of Single); overload;
  303. procedure Push(const Val: Single); inline;
  304. function Pop: Single; inline;
  305. procedure Insert(Index: Integer; const item: Single); inline;
  306. property Items[Index: Integer]: Single read Get write Put; default;
  307. property List: PSingleArrayList read FList;
  308. procedure AddSerie(aBase, aDelta: Single; aCount: Integer);
  309. // Adds delta to all items in the list
  310. procedure Offset(delta: Single); overload;
  311. (* Adds to each item the corresponding item in the delta list.
  312. Performs 'Items[i]:=Items[i]+delta[i]'.
  313. If both lists don't have the same item count, an exception is raised *)
  314. procedure Offset(const delta: TSingleList); overload;
  315. // Multiplies all items by factor
  316. procedure Scale(factor: Single);
  317. // Square all items
  318. procedure Sqr;
  319. // SquareRoot all items
  320. procedure Sqrt;
  321. // Computes the sum of all elements
  322. function Sum: Single;
  323. function Min: Single;
  324. function Max: Single;
  325. end;
  326. TDoubleArrayList = array[0..MaxInt shr 4] of Double;
  327. PDoubleArrayList = ^TDoubleArrayList;
  328. (* A list of Double.
  329. Similar to TList, but using Double as items.
  330. The list has stack-like push/pop methods *)
  331. TDoubleList = class(TBaseList)
  332. private
  333. FList: PDoubleArrayList;
  334. protected
  335. function Get(Index: Integer): Double;
  336. procedure Put(Index: Integer; const item: Double);
  337. procedure SetCapacity(NewCapacity: Integer); override;
  338. public
  339. constructor Create; override;
  340. procedure Assign(Src: TPersistent); override;
  341. function Add(const item: Double): Integer;
  342. procedure Push(const Val: Double);
  343. function Pop: Double;
  344. procedure Insert(Index: Integer; const item: Double);
  345. property Items[Index: Integer]: Double read Get write Put; default;
  346. property List: PDoubleArrayList read FList;
  347. procedure AddSerie(aBase, aDelta: Double; aCount: Integer);
  348. // Adds delta to all items in the list
  349. procedure Offset(delta: Double); overload;
  350. (* Adds to each item the corresponding item in the delta list.
  351. Performs 'Items[i]:=Items[i]+delta[i]'.
  352. If both lists don't have the same item count, an exception is raised *)
  353. procedure Offset(const delta: TDoubleList); overload;
  354. // Multiplies all items by factor
  355. procedure Scale(factor: Double);
  356. // Square all items
  357. procedure Sqr;
  358. // SquareRoot all items
  359. procedure Sqrt;
  360. // Computes the sum of all elements
  361. function Sum: Double;
  362. function Min: Single;
  363. function Max: Single;
  364. end;
  365. // A list of bytes. Similar to TList, but using Byte as items
  366. TByteList = class(TBaseList)
  367. private
  368. FList: PByteArray;
  369. protected
  370. function Get(Index: Integer): Byte; inline;
  371. procedure Put(Index: Integer; const item: Byte); inline;
  372. procedure SetCapacity(NewCapacity: Integer); override;
  373. public
  374. constructor Create; override;
  375. procedure Assign(Src: TPersistent); override;
  376. function Add(const item: Byte): Integer; inline;
  377. procedure Insert(Index: Integer; const item: Byte); inline;
  378. property Items[Index: Integer]: Byte read Get write Put; default;
  379. property List: PByteArray read FList;
  380. end;
  381. (* A list of TQuaternion.
  382. Similar to TList, but using TQuaternion as items.
  383. The list has stack-like push/pop methods *)
  384. TQuaternionList = class(TBaseVectorList)
  385. private
  386. FList: PQuaternionArray;
  387. protected
  388. function Get(Index: Integer): TQuaternion;
  389. procedure Put(Index: Integer; const item: TQuaternion);
  390. procedure SetCapacity(NewCapacity: Integer); override;
  391. public
  392. constructor Create; override;
  393. procedure Assign(Src: TPersistent); override;
  394. function Add(const item: TQuaternion): Integer; overload;
  395. function Add(const item: TAffineVector; w: Single): Integer; overload;
  396. function Add(const X, Y, Z, W: Single): Integer; overload;
  397. procedure Push(const Val: TQuaternion);
  398. function Pop: TQuaternion;
  399. function IndexOf(const item: TQuaternion): Integer;
  400. function FindOrAdd(const item: TQuaternion): Integer;
  401. procedure Insert(Index: Integer; const item: TQuaternion);
  402. property Items[Index: Integer]: TQuaternion read Get write Put; default;
  403. property List: PQuaternionArray read FList;
  404. // Lerps corresponding quaternions from both lists using QuaternionSlerp
  405. procedure Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single); override;
  406. (* Multiplies corresponding quaternions after the second quaternion is
  407. slerped with the IdentityQuaternion using factor. This allows for weighted
  408. combining of rotation transforms using quaternions *)
  409. procedure Combine(const list2: TBaseVectorList; factor: Single); override;
  410. end;
  411. // 4 byte union contain access like Integer, Single and four Byte
  412. T4ByteData = packed record
  413. case Byte of
  414. 0 : (Bytes : record Value : array[0..3] of Byte; end);
  415. 1 : (Int : record Value : Integer; end);
  416. 2 : (UInt : record Value : Cardinal; end);
  417. 3 : (Float : record Value : Single; end);
  418. 4 : (Word : record Value : array[0..1] of Word; end);
  419. end;
  420. T4ByteArrayList = array[0..MaxInt shr 4] of T4ByteData;
  421. P4ByteArrayList = ^T4ByteArrayList;
  422. // A list of T4ByteData
  423. T4ByteList = class(TBaseList)
  424. private
  425. FList: P4ByteArrayList;
  426. protected
  427. function Get(Index: Integer): T4ByteData;
  428. procedure Put(Index: Integer; const item: T4ByteData);
  429. procedure SetCapacity(NewCapacity: Integer); override;
  430. public
  431. constructor Create; override;
  432. procedure Assign(Src: TPersistent); override;
  433. function Add(const item: T4ByteData): Integer; overload;
  434. procedure Add(const i1: Single); overload;
  435. procedure Add(const i1, i2: Single); overload;
  436. procedure Add(const i1, i2, i3: Single); overload;
  437. procedure Add(const i1, i2, i3, i4: Single); overload;
  438. procedure Add(const i1: Integer); overload;
  439. procedure Add(const i1, i2: Integer); overload;
  440. procedure Add(const i1, i2, i3: Integer); overload;
  441. procedure Add(const i1, i2, i3, i4: Integer); overload;
  442. procedure Add(const i1: Cardinal); overload;
  443. procedure Add(const i1, i2: Cardinal); overload;
  444. procedure Add(const i1, i2, i3: Cardinal); overload;
  445. procedure Add(const i1, i2, i3, i4: Cardinal); overload;
  446. procedure Add(const AList: T4ByteList); overload;
  447. procedure Push(const Val: T4ByteData);
  448. function Pop: T4ByteData;
  449. procedure Insert(Index: Integer; const item: T4ByteData);
  450. property Items[Index: Integer]: T4ByteData read Get write Put; default;
  451. property List: P4ByteArrayList read FList;
  452. end;
  453. TLongWordList = class(TBaseList)
  454. private
  455. FList: PLongWordArray;
  456. protected
  457. function Get(Index: Integer): LongWord;
  458. procedure Put(Index: Integer; const item: LongWord);
  459. procedure SetCapacity(newCapacity: Integer); override;
  460. public
  461. constructor Create; override;
  462. procedure Assign(src: TPersistent); override;
  463. function Add(const item: LongWord): Integer; overload;
  464. function AddNC(const item: LongWord): Integer; overload;
  465. procedure Add(const i1, i2: LongWord); overload;
  466. procedure Add(const i1, i2, i3: LongWord); overload;
  467. procedure Add(const AList: TLongWordList); overload;
  468. procedure Push(const Val: LongWord);
  469. function Pop: LongWord;
  470. procedure Insert(Index: Integer; const item: LongWord);
  471. procedure Remove(const item: LongWord);
  472. function IndexOf(item: Integer): LongWord;
  473. property Items[Index: Integer]: LongWord read Get write Put; default;
  474. property List: PLongWordArray read FList;
  475. // Add n integers at the address starting at (and including) first
  476. procedure AddLongWords(const First: PLongWord; n: Integer); overload;
  477. // Add all integers from aList into the list
  478. procedure AddLongWords(const aList: TLongWordList); overload;
  479. // Add all integers from anArray into the list
  480. procedure AddLongWords(const anArray: array of LongWord); overload;
  481. end;
  482. // Sort the refList in ascending order, ordering objList (TList) on the way
  483. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TSingleList; objList: TList); overload;
  484. // Sort the refList in ascending order, ordering objList (TBaseList) on the way
  485. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TSingleList; objList: TBaseList); overload;
  486. (* Sort the refList in ascending order, ordering objList on the way.
  487. Use if, and *ONLY* if refList contains only values superior or equal to 1 *)
  488. procedure FastQuickSortLists(startIndex, endIndex: Integer; const refList: TSingleList; const objList: TPersistentObjectList);
  489. // ------------------------------------------------------------------
  490. implementation
  491. // ------------------------------------------------------------------
  492. const
  493. cDefaultListGrowthDelta = 16;
  494. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TSingleList; objList: TList);
  495. var
  496. I, J: Integer;
  497. P: Single;
  498. begin
  499. if endIndex - startIndex > 1 then
  500. begin
  501. repeat
  502. I := startIndex;
  503. J := endIndex;
  504. P := refList.List^[(I + J) shr 1];
  505. repeat
  506. while Single(refList.List^[I]) < P do
  507. Inc(I);
  508. while Single(refList.List^[J]) > P do
  509. Dec(J);
  510. if I <= J then
  511. begin
  512. refList.Exchange(I, J);
  513. objList.Exchange(I, J);
  514. Inc(I);
  515. Dec(J);
  516. end;
  517. until I > J;
  518. if startIndex < J then
  519. QuickSortLists(startIndex, J, refList, objList);
  520. startIndex := I;
  521. until I >= endIndex;
  522. end
  523. else
  524. if endIndex - startIndex > 0 then
  525. begin
  526. p := refList.List^[startIndex];
  527. if refList.List^[endIndex] < p then
  528. begin
  529. refList.Exchange(startIndex, endIndex);
  530. objList.Exchange(startIndex, endIndex);
  531. end;
  532. end;
  533. end;
  534. procedure QuickSortLists(startIndex, endIndex: Integer; refList: TSingleList; objList: TBaseList);
  535. var
  536. I, J: Integer;
  537. P: Single;
  538. begin
  539. if endIndex - startIndex > 1 then
  540. begin
  541. repeat
  542. I := startIndex;
  543. J := endIndex;
  544. P := refList.List^[(I + J) shr 1];
  545. repeat
  546. while Single(refList.List^[I]) < P do
  547. Inc(I);
  548. while Single(refList.List^[J]) > P do
  549. Dec(J);
  550. if I <= J then
  551. begin
  552. refList.Exchange(I, J);
  553. objList.Exchange(I, J);
  554. Inc(I);
  555. Dec(J);
  556. end;
  557. until I > J;
  558. if startIndex < J then
  559. QuickSortLists(startIndex, J, refList, objList);
  560. startIndex := I;
  561. until I >= endIndex;
  562. end
  563. else
  564. if endIndex - startIndex > 0 then
  565. begin
  566. p := refList.List^[startIndex];
  567. if refList.List^[endIndex] < p then
  568. begin
  569. refList.Exchange(startIndex, endIndex);
  570. objList.Exchange(startIndex, endIndex);
  571. end;
  572. end;
  573. end;
  574. procedure FastInsertionSortLists(startIndex, endIndex: Integer; const ppl: PIntegerArray; const oppl: PPointerArray); inline;
  575. var
  576. oTemp: Pointer;
  577. I, J: Integer;
  578. Temp: Integer;
  579. begin
  580. for I := startIndex+1 to endIndex-1 do
  581. begin
  582. J := i-1;
  583. Temp := ppl^[I];
  584. oTemp := oppl^[I];
  585. while (J>=startIndex) and (Temp < ppl^[J]) do
  586. begin
  587. ppl^[J+1] := ppl^[J];
  588. oppl^[J+1] := oppl^[J];
  589. Dec(j);
  590. end;
  591. ppl^[J+1] := Temp;
  592. oppl^[J+1] := oTemp;
  593. end;
  594. end;
  595. procedure FastQuickSortLists(startIndex, endIndex: Integer; const refList: TSingleList; const objList: TPersistentObjectList);
  596. var
  597. ppl: PIntegerArray;
  598. oTemp: Pointer;
  599. oppl: PPointerArray;
  600. I, J: Integer;
  601. p, Temp: Integer;
  602. begin
  603. // All singles are >=1, so IEEE format allows comparing them as if they were integers
  604. ppl := PIntegerArray(@refList.List[0]);
  605. oppl := PPointerArray(objList.List);
  606. if endIndex > startIndex + 1 then
  607. begin
  608. if (endIndex-startIndex)<16 then
  609. begin
  610. FastInsertionSortLists(startIndex, endIndex, ppl, oppl);
  611. end else
  612. begin
  613. repeat
  614. I := startIndex;
  615. J := endIndex;
  616. p := PInteger(@refList.List[(I + J) shr 1])^;
  617. repeat
  618. while ppl^[I] < p do
  619. Inc(I);
  620. while ppl^[J] > p do
  621. Dec(J);
  622. if I <= J then
  623. begin
  624. // swap integers
  625. Temp := ppl^[I];
  626. ppl^[I] := ppl^[J];
  627. ppl^[J] := Temp;
  628. // swap pointers
  629. oTemp := oppl^[I];
  630. oppl^[I] := oppl^[J];
  631. oppl^[J] := oTemp;
  632. Inc(I);
  633. Dec(J);
  634. end;
  635. until I > J;
  636. if startIndex < J then
  637. FastQuickSortLists(startIndex, J, refList, objList);
  638. startIndex := I;
  639. until I >= endIndex;
  640. end;
  641. end else if endIndex > startIndex then
  642. begin
  643. if ppl^[endIndex] < ppl^[startIndex] then
  644. begin
  645. I := endIndex;
  646. J := startIndex;
  647. // swap integers
  648. Temp := ppl^[I];
  649. ppl^[I] := ppl^[J];
  650. ppl^[J] := Temp;
  651. // swap pointers
  652. oTemp := oppl^[I];
  653. oppl^[I] := oppl^[J];
  654. oppl^[J] := oTemp;
  655. end;
  656. end;
  657. end;
  658. // ------------------
  659. // ------------------ TBaseList ------------------
  660. // ------------------
  661. constructor TBaseList.Create;
  662. begin
  663. inherited Create;
  664. FOptions := [bloSetCountResetsMemory];
  665. end;
  666. destructor TBaseList.Destroy;
  667. begin
  668. Clear;
  669. if Assigned(FBufferItem) then
  670. FreeMem(FBufferItem);
  671. inherited;
  672. end;
  673. procedure TBaseList.Assign(Src: TPersistent);
  674. begin
  675. if (Src is TBaseList) then
  676. begin
  677. SetCapacity(TBaseList(Src).Count);
  678. FGrowthDelta := TBaseList(Src).FGrowthDelta;
  679. FCount := FCapacity;
  680. FTagString := TBaseList(Src).FTagString;
  681. Inc(FRevision);
  682. end
  683. else
  684. inherited;
  685. end;
  686. procedure TBaseList.DefineProperties(AFiler: TFiler);
  687. begin
  688. inherited DefineProperties(AFiler);
  689. AFiler.DefineProperty('Items', ReadItemsData, WriteItemsData, True);
  690. end;
  691. procedure TBaseList.ReadItemsData(AReader: TReader);
  692. var
  693. lData: AnsiString;
  694. lOutputText: string;
  695. begin
  696. lOutputText := AReader.ReadString;
  697. SetLength(lData, Length(lOutputText) div 2 + 1);
  698. HexToBin(PChar(lOutputText), PAnsiChar(lData), Length(lData));
  699. LoadFromString(string(lData));
  700. end;
  701. procedure TBaseList.WriteItemsData(AWriter: TWriter);
  702. var
  703. lData: AnsiString;
  704. lOutputText: String;
  705. begin
  706. lData := AnsiString(SaveToString);
  707. SetLength(lOutputText, Length(lData) * 2);
  708. BinToHex(PAnsiChar(lData), PChar(lOutputText), Length(lData));
  709. AWriter.WriteString(lOutputText);
  710. end;
  711. procedure TBaseList.WriteToFiler(writer: TVirtualWriter);
  712. begin
  713. inherited;
  714. with writer do
  715. begin
  716. WriteInteger(0); // Archive Version 0
  717. WriteInteger(Count);
  718. WriteInteger(FItemSize);
  719. if Count > 0 then
  720. write(FBaseList[0], Count * FItemSize);
  721. end;
  722. end;
  723. procedure TBaseList.ReadFromFiler(reader: TVirtualReader);
  724. var
  725. archiveVersion: Integer;
  726. begin
  727. inherited;
  728. archiveVersion := reader.ReadInteger;
  729. if archiveVersion = 0 then
  730. with reader do
  731. begin
  732. FCount := ReadInteger;
  733. FItemSize := ReadInteger;
  734. SetCapacity(Count);
  735. if Count > 0 then
  736. read(FBaseList[0], Count * FItemSize);
  737. end
  738. else
  739. RaiseFilerException(archiveVersion);
  740. Inc(FRevision);
  741. end;
  742. procedure TBaseList.SetCount(Val: Integer);
  743. begin
  744. Assert(Val >= 0);
  745. if Val > FCapacity then
  746. SetCapacity(Val);
  747. if (Val > FCount) and (bloSetCountResetsMemory in FOptions) then
  748. FillChar(FBaseList[FItemSize * FCount], (Val - FCount) * FItemSize, 0);
  749. FCount := Val;
  750. Inc(FRevision);
  751. end;
  752. procedure TBaseList.SetCapacity(newCapacity: Integer);
  753. begin
  754. if newCapacity <> FCapacity then
  755. begin
  756. if bloExternalMemory in FOptions then
  757. begin
  758. Exclude(FOptions, bloExternalMemory);
  759. FBaseList := nil;
  760. end;
  761. ReallocMem(FBaseList, newCapacity * FItemSize);
  762. FCapacity := newCapacity;
  763. Inc(FRevision);
  764. end;
  765. end;
  766. procedure TBaseList.AddNulls(nbVals: Cardinal);
  767. begin
  768. if Integer(nbVals) + Count > Capacity then
  769. SetCapacity(Integer(nbVals) + Count);
  770. FillChar(FBaseList[FCount * FItemSize], Integer(nbVals) * FItemSize, 0);
  771. FCount := FCount + Integer(nbVals);
  772. Inc(FRevision);
  773. end;
  774. procedure TBaseList.InsertNulls(Index: Integer; nbVals: Cardinal);
  775. var
  776. nc: Integer;
  777. begin
  778. {$IFOPT R+}
  779. Assert(Cardinal(Index) < Cardinal(FCount));
  780. {$ENDIF}
  781. if nbVals > 0 then
  782. begin
  783. nc := FCount + Integer(nbVals);
  784. if nc > FCapacity then
  785. SetCapacity(nc);
  786. if Index < FCount then
  787. System.Move(FBaseList[Index * FItemSize],
  788. FBaseList[(Index + Integer(nbVals)) * FItemSize],
  789. (FCount - Index) * FItemSize);
  790. FillChar(FBaseList[Index * FItemSize], Integer(nbVals) * FItemSize, 0);
  791. FCount := nc;
  792. Inc(FRevision);
  793. end;
  794. end;
  795. procedure TBaseList.AdjustCapacityToAtLeast(const size: Integer);
  796. begin
  797. if Capacity < size then
  798. Capacity := size;
  799. end;
  800. function TBaseList.DataSize: Integer;
  801. begin
  802. Result := FItemSize * FCount;
  803. end;
  804. function TBaseList.BufferItem: PByteArray;
  805. begin
  806. if not Assigned(FBufferItem) then
  807. GetMem(FBufferItem, FItemSize);
  808. Result := FBufferItem;
  809. end;
  810. function TBaseList.GetSetCountResetsMemory: Boolean;
  811. begin
  812. Result := (bloSetCountResetsMemory in FOptions);
  813. end;
  814. procedure TBaseList.SetSetCountResetsMemory(const Val: Boolean);
  815. begin
  816. if Val then
  817. Include(FOptions, bloSetCountResetsMemory)
  818. else
  819. Exclude(FOptions, bloSetCountResetsMemory);
  820. end;
  821. procedure TBaseList.UseMemory(rangeStart: Pointer; rangeCapacity: Integer);
  822. begin
  823. rangeCapacity := rangeCapacity div FItemSize;
  824. if rangeCapacity < FCount then
  825. Exit;
  826. // transfer data
  827. System.Move(FBaseList^, rangeStart^, FCount * FItemSize);
  828. if not (bloExternalMemory in FOptions) then
  829. begin
  830. FreeMem(FBaseList);
  831. Include(FOptions, bloExternalMemory);
  832. end;
  833. FBaseList := rangeStart;
  834. FCapacity := rangeCapacity;
  835. SetCapacity(FCapacity); // notify subclasses
  836. end;
  837. procedure TBaseList.Flush;
  838. begin
  839. if Assigned(Self) then
  840. begin
  841. SetCount(0);
  842. end;
  843. end;
  844. procedure TBaseList.Clear;
  845. begin
  846. if Assigned(Self) then
  847. begin
  848. SetCount(0);
  849. SetCapacity(0);
  850. end;
  851. end;
  852. procedure TBaseList.Delete(Index: Integer);
  853. begin
  854. {$IFOPT R+}
  855. Assert(Cardinal(index) < Cardinal(FCount));
  856. {$ENDIF}
  857. Dec(FCount);
  858. if Index < FCount then
  859. System.Move(FBaseList[(Index + 1) * FItemSize],
  860. FBaseList[Index * FItemSize],
  861. (FCount - Index) * FItemSize);
  862. Inc(FRevision);
  863. end;
  864. procedure TBaseList.DeleteItems(Index: Integer; nbVals: Cardinal);
  865. begin
  866. {$IFOPT R+}
  867. Assert(Cardinal(index) < Cardinal(FCount));
  868. {$ENDIF}
  869. if nbVals > 0 then
  870. begin
  871. if Index + Integer(nbVals) < FCount then
  872. begin
  873. System.Move(FBaseList[(Index + Integer(nbVals)) * FItemSize],
  874. FBaseList[Index * FItemSize],
  875. (FCount - Index - Integer(nbVals)) * FItemSize);
  876. end;
  877. Dec(FCount, nbVals);
  878. Inc(FRevision);
  879. end;
  880. end;
  881. procedure TBaseList.Exchange(index1, index2: Integer);
  882. var
  883. buf: Integer;
  884. p: PIntegerArray;
  885. begin
  886. {$IFOPT R+}
  887. Assert((Cardinal(index1) < Cardinal(FCount)) and (Cardinal(index2) < Cardinal(FCount)));
  888. {$ENDIF}
  889. if FItemSize = 4 then
  890. begin
  891. p := PIntegerArray(FBaseList);
  892. buf := p^[index1];
  893. p^[index1] := p^[index2];
  894. p^[index2] := buf;
  895. end
  896. else
  897. begin
  898. System.Move(FBaseList[index1 * FItemSize], BufferItem[0], FItemSize);
  899. System.Move(FBaseList[index2 * FItemSize], FBaseList[index1 * FItemSize], FItemSize);
  900. System.Move(BufferItem[0], FBaseList[index2 * FItemSize], FItemSize);
  901. end;
  902. Inc(FRevision);
  903. end;
  904. procedure TBaseList.Move(curIndex, newIndex: Integer);
  905. begin
  906. if curIndex <> newIndex then
  907. begin
  908. {$IFOPT R+}
  909. Assert(Cardinal(newIndex) < Cardinal(Count));
  910. Assert(Cardinal(curIndex) < Cardinal(Count));
  911. {$ENDIF}
  912. if FItemSize = 4 then
  913. PInteger(BufferItem)^ := PInteger(@FBaseList[curIndex * FItemSize])^
  914. else
  915. System.Move(FBaseList[curIndex * FItemSize], BufferItem[0], FItemSize);
  916. if curIndex < newIndex then
  917. begin
  918. // curIndex+1 necessarily exists since curIndex<newIndex and newIndex<Count
  919. System.Move(FBaseList[(curIndex + 1) * FItemSize], FBaseList[curIndex * FItemSize],
  920. (newIndex - curIndex) * FItemSize);
  921. end
  922. else
  923. begin
  924. // newIndex+1 necessarily exists since newIndex<curIndex and curIndex<Count
  925. System.Move(FBaseList[newIndex * FItemSize], FBaseList[(newIndex + 1) * FItemSize],
  926. (curIndex - newIndex) * FItemSize);
  927. end;
  928. if FItemSize = 4 then
  929. PInteger(@FBaseList[newIndex * FItemSize])^ := PInteger(BufferItem)^
  930. else
  931. System.Move(BufferItem[0], FBaseList[newIndex * FItemSize], FItemSize);
  932. Inc(FRevision);
  933. end;
  934. end;
  935. procedure TBaseList.Reverse;
  936. var
  937. s, e: Integer;
  938. begin
  939. s := 0;
  940. e := Count - 1;
  941. while s < e do
  942. begin
  943. Exchange(s, e);
  944. Inc(s);
  945. Dec(e);
  946. end;
  947. Inc(FRevision);
  948. end;
  949. // ------------------
  950. // ------------------ TBaseVectorList ------------------
  951. // ------------------
  952. procedure TBaseVectorList.WriteToFiler(writer: TVirtualWriter);
  953. begin
  954. inherited;
  955. if Self is TTexPointList then
  956. exit;
  957. with writer do
  958. begin
  959. WriteInteger(0); // Archive Version 0
  960. // nothing
  961. end;
  962. end;
  963. procedure TBaseVectorList.ReadFromFiler(reader: TVirtualReader);
  964. var
  965. archiveVersion: Integer;
  966. begin
  967. inherited;
  968. if Self is TTexPointList then
  969. exit;
  970. archiveVersion := reader.ReadInteger;
  971. if archiveVersion = 0 then
  972. with reader do
  973. begin
  974. // nothing
  975. end
  976. else
  977. RaiseFilerException(archiveVersion);
  978. end;
  979. procedure TBaseVectorList.GetExtents(out min, max: TAffineVector);
  980. var
  981. I, K: Integer;
  982. f: Single;
  983. ref: PFloatArray;
  984. const
  985. cBigValue: Single = 1E50;
  986. cSmallValue: Single = -1E50;
  987. begin
  988. SetVector(min, cBigValue, cBigValue, cBigValue);
  989. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  990. for I := 0 to Count - 1 do
  991. begin
  992. ref := ItemAddress[I];
  993. for K := 0 to 2 do
  994. begin
  995. f := ref^[K];
  996. if f < min.V[K] then
  997. min.V[K] := f;
  998. if f > max.V[K] then
  999. max.V[K] := f;
  1000. end;
  1001. end;
  1002. end;
  1003. function TBaseVectorList.Sum: TAffineVector;
  1004. var
  1005. I: Integer;
  1006. begin
  1007. Result := NullVector;
  1008. for I := 0 to Count - 1 do
  1009. AddVector(Result, PAffineVector(ItemAddress[I])^);
  1010. end;
  1011. procedure TBaseVectorList.Normalize;
  1012. var
  1013. I: Integer;
  1014. begin
  1015. for I := 0 to Count - 1 do
  1016. NormalizeVector(PAffineVector(ItemAddress[I])^);
  1017. Inc(FRevision);
  1018. end;
  1019. function TBaseVectorList.MaxSpacing(list2: TBaseVectorList): Single;
  1020. var
  1021. I: Integer;
  1022. s: Single;
  1023. begin
  1024. Assert(list2.Count = Count);
  1025. Result := 0;
  1026. for I := 0 to Count - 1 do
  1027. begin
  1028. s := VectorSpacing(PAffineVector(ItemAddress[I])^,
  1029. PAffineVector(list2.ItemAddress[I])^);
  1030. if s > Result then
  1031. Result := s;
  1032. end;
  1033. end;
  1034. procedure TBaseVectorList.Translate(const delta: TAffineVector);
  1035. var
  1036. I: Integer;
  1037. begin
  1038. for I := 0 to Count - 1 do
  1039. AddVector(PAffineVector(ItemAddress[I])^, delta);
  1040. Inc(FRevision);
  1041. end;
  1042. procedure TBaseVectorList.Translate(const delta: TBaseVectorList);
  1043. var
  1044. I: Integer;
  1045. begin
  1046. Assert(Count <= delta.Count);
  1047. for I := 0 to Count - 1 do
  1048. AddVector(PAffineVector(ItemAddress[I])^, PAffineVector(delta.ItemAddress[I])^);
  1049. Inc(FRevision);
  1050. end;
  1051. procedure TBaseVectorList.TranslateInv(const delta: TBaseVectorList);
  1052. var
  1053. I: Integer;
  1054. begin
  1055. Assert(Count <= delta.Count);
  1056. for I := 0 to Count - 1 do
  1057. SubtractVector(PAffineVector(ItemAddress[I])^, PAffineVector(delta.ItemAddress[I])^);
  1058. Inc(FRevision);
  1059. end;
  1060. procedure TBaseVectorList.AngleLerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  1061. var
  1062. I: Integer;
  1063. begin
  1064. Assert(list1.Count = list2.Count);
  1065. if list1 <> list2 then
  1066. begin
  1067. if lerpFactor = 0 then
  1068. Assign(list1)
  1069. else
  1070. if lerpFactor = 1 then
  1071. Assign(list2)
  1072. else
  1073. begin
  1074. Capacity := list1.Count;
  1075. FCount := list1.Count;
  1076. for I := 0 to list1.Count - 1 do
  1077. PAffineVector(ItemAddress[I])^ := VectorAngleLerp(PAffineVector(list1.ItemAddress[I])^,
  1078. PAffineVector(list2.ItemAddress[I])^,
  1079. lerpFactor);
  1080. end;
  1081. end
  1082. else
  1083. Assign(list1);
  1084. Inc(FRevision);
  1085. end;
  1086. procedure TBaseVectorList.AngleCombine(const list1: TBaseVectorList; intensity: Single);
  1087. var
  1088. I: Integer;
  1089. begin
  1090. Assert(list1.Count = Count);
  1091. for I := 0 to Count - 1 do
  1092. PAffineVector(ItemAddress[I])^ := VectorAngleCombine(PAffineVector(ItemAddress[I])^,
  1093. PAffineVector(list1.ItemAddress[I])^,
  1094. intensity);
  1095. Inc(FRevision);
  1096. end;
  1097. procedure TBaseVectorList.Combine(const list2: TBaseVectorList; factor: Single);
  1098. var
  1099. I: Integer;
  1100. begin
  1101. Assert(list2.Count >= Count);
  1102. for I := 0 to Count - 1 do
  1103. CombineVector(PAffineVector(ItemAddress[I])^,
  1104. PAffineVector(list2.ItemAddress[I])^,
  1105. factor);
  1106. Inc(FRevision);
  1107. end;
  1108. function TBaseVectorList.GetItemAddress(Index: Integer): PFloatArray;
  1109. begin
  1110. {$IFOPT R+}
  1111. Assert(Cardinal(Index) < Cardinal(FCount));
  1112. {$ENDIF}
  1113. Result := PFloatArray(@FBaseList[Index * FItemSize]);
  1114. end;
  1115. // ------------------
  1116. // ------------------ TAffineVectorList ------------------
  1117. // ------------------
  1118. constructor TAffineVectorList.Create;
  1119. begin
  1120. FItemSize := SizeOf(TAffineVector);
  1121. inherited Create;
  1122. FGrowthDelta := cDefaultListGrowthDelta;
  1123. end;
  1124. procedure TAffineVectorList.Assign(Src: TPersistent);
  1125. begin
  1126. if Assigned(Src) then
  1127. begin
  1128. inherited;
  1129. if (Src is TAffineVectorList) then
  1130. System.Move(TAffineVectorList(Src).FList^, FList^, FCount * SizeOf(TAffineVector));
  1131. end
  1132. else
  1133. Clear;
  1134. end;
  1135. function TAffineVectorList.Add(const item: TAffineVector): Integer;
  1136. begin
  1137. Result := FCount;
  1138. if Result = FCapacity then
  1139. SetCapacity(FCapacity + FGrowthDelta);
  1140. FList^[Result] := Item;
  1141. Inc(FCount);
  1142. Inc(FRevision);
  1143. end;
  1144. function TAffineVectorList.Add(const item: TGLVector): Integer;
  1145. begin
  1146. Result := Add(PAffineVector(@item)^);
  1147. end;
  1148. procedure TAffineVectorList.Add(const i1, i2: TAffineVector);
  1149. begin
  1150. Inc(FCount, 2);
  1151. while FCount > FCapacity do
  1152. SetCapacity(FCapacity + FGrowthDelta);
  1153. FList^[FCount - 2] := i1;
  1154. FList^[FCount - 1] := i2;
  1155. Inc(FRevision);
  1156. end;
  1157. procedure TAffineVectorList.Add(const i1, i2, i3: TAffineVector);
  1158. begin
  1159. Inc(FCount, 3);
  1160. while FCount > FCapacity do
  1161. SetCapacity(FCapacity + FGrowthDelta);
  1162. FList^[FCount - 3] := i1;
  1163. FList^[FCount - 2] := i2;
  1164. FList^[FCount - 1] := i3;
  1165. Inc(FRevision);
  1166. end;
  1167. function TAffineVectorList.Add(const item: TVector2f): Integer;
  1168. begin
  1169. Result := Add(AffineVectorMake(item.X, item.Y, 0));
  1170. end;
  1171. function TAffineVectorList.Add(const item: TTexPoint): Integer;
  1172. begin
  1173. Result := Add(AffineVectorMake(item.S, item.T, 0));
  1174. end;
  1175. function TAffineVectorList.Add(const X, Y: Single): Integer;
  1176. var
  1177. v: PAffineVector;
  1178. begin
  1179. Result := FCount;
  1180. Inc(FCount);
  1181. while FCount > FCapacity do
  1182. SetCapacity(FCapacity + FGrowthDelta);
  1183. v := @List[Result];
  1184. v^.X := X;
  1185. v^.Y := Y;
  1186. v^.Z := 0;
  1187. Inc(FRevision);
  1188. end;
  1189. function TAffineVectorList.Add(const X, Y, Z: Single): Integer;
  1190. var
  1191. v: PAffineVector;
  1192. begin
  1193. Result := FCount;
  1194. Inc(FCount);
  1195. while FCount > FCapacity do
  1196. SetCapacity(FCapacity + FGrowthDelta);
  1197. v := @List[Result];
  1198. v^.X := X;
  1199. v^.Y := Y;
  1200. v^.Z := Z;
  1201. Inc(FRevision);
  1202. end;
  1203. function TAffineVectorList.Add(const X, Y, Z: Integer): Integer;
  1204. var
  1205. v: PAffineVector;
  1206. begin
  1207. Result := FCount;
  1208. if Result = FCapacity then
  1209. SetCapacity(FCapacity + FGrowthDelta);
  1210. v := @List[Result];
  1211. v^.X := X;
  1212. v^.Y := Y;
  1213. v^.Z := Z;
  1214. Inc(FCount);
  1215. Inc(FRevision);
  1216. end;
  1217. function TAffineVectorList.AddNC(const X, Y, Z: Integer): Integer;
  1218. var
  1219. v: PAffineVector;
  1220. begin
  1221. Result := FCount;
  1222. v := @List[Result];
  1223. v^.X := X;
  1224. v^.Y := Y;
  1225. v^.Z := Z;
  1226. Inc(FCount);
  1227. Inc(FRevision);
  1228. end;
  1229. function TAffineVectorList.Add(const xy: PIntegerArray; const Z: Integer): Integer;
  1230. var
  1231. v: PAffineVector;
  1232. begin
  1233. Result := FCount;
  1234. if Result = FCapacity then
  1235. SetCapacity(FCapacity + FGrowthDelta);
  1236. v := @List[Result];
  1237. v^.X := xy^[0];
  1238. v^.Y := xy^[1];
  1239. v^.Z := Z;
  1240. Inc(FCount);
  1241. Inc(FRevision);
  1242. end;
  1243. function TAffineVectorList.AddNC(const xy: PIntegerArray; const Z: Integer): Integer;
  1244. var
  1245. v: PAffineVector;
  1246. begin
  1247. Result := FCount;
  1248. v := @List[Result];
  1249. v^.X := xy^[0];
  1250. v^.Y := xy^[1];
  1251. v^.Z := Z;
  1252. Inc(FCount);
  1253. Inc(FRevision);
  1254. end;
  1255. procedure TAffineVectorList.Add(const list: TAffineVectorList);
  1256. begin
  1257. if Assigned(list) and (list.Count > 0) then
  1258. begin
  1259. if Count + list.Count > Capacity then
  1260. Capacity := Count + list.Count;
  1261. System.Move(list.FList[0], FList[Count], list.Count * SizeOf(TAffineVector));
  1262. Inc(FCount, list.Count);
  1263. end;
  1264. Inc(FRevision);
  1265. end;
  1266. function TAffineVectorList.Get(Index: Integer): TAffineVector;
  1267. begin
  1268. {$IFOPT R+}
  1269. Assert(Cardinal(Index) < Cardinal(FCount));
  1270. {$ENDIF}
  1271. Result := FList^[Index];
  1272. end;
  1273. procedure TAffineVectorList.Insert(Index: Integer; const Item: TAffineVector);
  1274. begin
  1275. {$IFOPT R+}
  1276. Assert(Cardinal(Index) < Cardinal(FCount));
  1277. {$ENDIF}
  1278. if FCount = FCapacity then
  1279. SetCapacity(FCapacity + FGrowthDelta);
  1280. if Index < FCount then
  1281. System.Move(FList[Index], FList[Index + 1],
  1282. (FCount - Index) * SizeOf(TAffineVector));
  1283. FList^[Index] := Item;
  1284. Inc(FCount);
  1285. Inc(FRevision);
  1286. end;
  1287. function TAffineVectorList.IndexOf(const item: TAffineVector): Integer;
  1288. var
  1289. I: Integer;
  1290. begin
  1291. Result := -1;
  1292. for I := 0 to Count - 1 do
  1293. if VectorEquals(item, FList^[I]) then
  1294. begin
  1295. Result := I;
  1296. Break;
  1297. end;
  1298. end;
  1299. function TAffineVectorList.FindOrAdd(const item: TAffineVector): Integer;
  1300. begin
  1301. Result := IndexOf(item);
  1302. if Result < 0 then
  1303. begin
  1304. Result := Add(item);
  1305. Inc(FRevision);
  1306. end;
  1307. end;
  1308. procedure TAffineVectorList.Put(Index: Integer; const Item: TAffineVector);
  1309. begin
  1310. {$IFOPT R+}
  1311. Assert(Cardinal(Index) < Cardinal(FCount));
  1312. {$ENDIF}
  1313. FList^[Index] := Item;
  1314. Inc(FRevision);
  1315. end;
  1316. procedure TAffineVectorList.SetCapacity(NewCapacity: Integer);
  1317. begin
  1318. inherited;
  1319. FList := PAffineVectorArray(FBaseList);
  1320. end;
  1321. procedure TAffineVectorList.Push(const Val: TAffineVector);
  1322. begin
  1323. Add(Val);
  1324. end;
  1325. function TAffineVectorList.Pop: TAffineVector;
  1326. begin
  1327. if FCount > 0 then
  1328. begin
  1329. Result := Get(FCount - 1);
  1330. Delete(FCount - 1);
  1331. Inc(FRevision);
  1332. end
  1333. else
  1334. Result := NullVector;
  1335. end;
  1336. procedure TAffineVectorList.Translate(const delta: TAffineVector);
  1337. begin
  1338. VectorArrayAdd(FList, delta, Count, FList);
  1339. Inc(FRevision);
  1340. end;
  1341. procedure TAffineVectorList.Translate(const delta: TAffineVector; base, nb: Integer);
  1342. begin
  1343. VectorArrayAdd(@FList[base], delta, nb, @FList[base]);
  1344. Inc(FRevision);
  1345. end;
  1346. procedure TAffineVectorList.TranslateItem(Index: Integer; const delta: TAffineVector);
  1347. begin
  1348. {$IFOPT R+}
  1349. Assert(Cardinal(Index) < Cardinal(FCount));
  1350. {$ENDIF}
  1351. AddVector(FList^[Index], delta);
  1352. Inc(FRevision);
  1353. end;
  1354. procedure TAffineVectorList.TranslateItems(Index: Integer; const delta: TAffineVector; nb: Integer);
  1355. begin
  1356. nb := Index + nb;
  1357. {$IFOPT R+}
  1358. Assert(Cardinal(index) < Cardinal(FCount));
  1359. if nb > FCount then
  1360. nb := FCount;
  1361. {$ENDIF}
  1362. VectorArrayAdd(@FList[Index], delta, nb - Index, @FList[Index]);
  1363. Inc(FRevision);
  1364. end;
  1365. procedure TAffineVectorList.CombineItem(Index: Integer; const vector: TAffineVector; const f: Single);
  1366. begin
  1367. {$IFOPT R+}
  1368. Assert(Cardinal(Index) < Cardinal(FCount));
  1369. {$ENDIF}
  1370. CombineVector(FList^[Index], vector, @f);
  1371. Inc(FRevision);
  1372. end;
  1373. procedure TAffineVectorList.TransformAsPoints(const matrix: TGLMatrix);
  1374. var
  1375. I: Integer;
  1376. begin
  1377. for I := 0 to FCount - 1 do
  1378. FList^[I] := VectorTransform(FList^[I], matrix);
  1379. Inc(FRevision);
  1380. end;
  1381. procedure TAffineVectorList.TransformAsVectors(const matrix: TGLMatrix);
  1382. var
  1383. m: TAffineMatrix;
  1384. begin
  1385. if FCount > 0 then
  1386. begin
  1387. SetMatrix(m, matrix);
  1388. TransformAsVectors(m);
  1389. end;
  1390. end;
  1391. procedure TAffineVectorList.TransformAsVectors(const matrix: TAffineMatrix);
  1392. var
  1393. I: Integer;
  1394. begin
  1395. for I := 0 to FCount - 1 do
  1396. FList^[I] := VectorTransform(FList^[I], matrix);
  1397. Inc(FRevision);
  1398. end;
  1399. procedure TAffineVectorList.Normalize;
  1400. begin
  1401. NormalizeVectorArray(List, Count);
  1402. Inc(FRevision);
  1403. end;
  1404. procedure TAffineVectorList.Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  1405. begin
  1406. if (list1 is TAffineVectorList) and (list2 is TAffineVectorList) then
  1407. begin
  1408. Assert(list1.Count = list2.Count);
  1409. Capacity := list1.Count;
  1410. FCount := list1.Count;
  1411. VectorArrayLerp(TAffineVectorList(list1).List, TAffineVectorList(list2).List,
  1412. lerpFactor, FCount, List);
  1413. Inc(FRevision);
  1414. end;
  1415. end;
  1416. procedure TAffineVectorList.Scale(factor: Single);
  1417. begin
  1418. if (Count > 0) and (factor <> 1) then
  1419. begin
  1420. ScaleFloatArray(@FList[0].X, Count * 3, factor);
  1421. Inc(FRevision);
  1422. end;
  1423. end;
  1424. procedure TAffineVectorList.Scale(const factors: TAffineVector);
  1425. var
  1426. I: Integer;
  1427. begin
  1428. for I := 0 to Count - 1 do
  1429. ScaleVector(FList^[I], factors);
  1430. Inc(FRevision);
  1431. end;
  1432. // ------------------
  1433. // ------------------ TVectorList ------------------
  1434. // ------------------
  1435. constructor TVectorList.Create;
  1436. begin
  1437. FItemSize := SizeOf(TGLVector);
  1438. inherited Create;
  1439. FGrowthDelta := cDefaultListGrowthDelta;
  1440. end;
  1441. procedure TVectorList.Assign(Src: TPersistent);
  1442. begin
  1443. if Assigned(Src) then
  1444. begin
  1445. inherited;
  1446. if (Src is TVectorList) then
  1447. System.Move(TVectorList(Src).FList^, FList^, FCount * SizeOf(TGLVector));
  1448. end
  1449. else
  1450. Clear;
  1451. end;
  1452. function TVectorList.Add(const item: TGLVector): Integer;
  1453. begin
  1454. Result := FCount;
  1455. if Result = FCapacity then
  1456. SetCapacity(FCapacity + FGrowthDelta);
  1457. FList^[Result] := Item;
  1458. Inc(FCount);
  1459. end;
  1460. function TVectorList.Add(const item: TAffineVector; w: Single): Integer;
  1461. begin
  1462. Result := Add(VectorMake(item, w));
  1463. end;
  1464. function TVectorList.Add(const X, Y, Z, w: Single): Integer;
  1465. begin
  1466. Result := Add(VectorMake(X, Y, Z, w));
  1467. end;
  1468. procedure TVectorList.Add(const i1, i2, i3: TAffineVector; w: Single);
  1469. begin
  1470. Inc(FCount, 3);
  1471. while FCount > FCapacity do
  1472. SetCapacity(FCapacity + FGrowthDelta);
  1473. PAffineVector(@FList[FCount - 3])^ := i1;
  1474. FList^[FCount - 3].W := w;
  1475. PAffineVector(@FList[FCount - 2])^ := i2;
  1476. FList^[FCount - 2].W := w;
  1477. PAffineVector(@FList[FCount - 1])^ := i3;
  1478. FList^[FCount - 1].W := w;
  1479. end;
  1480. function TVectorList.AddVector(const item: TAffineVector): Integer;
  1481. begin
  1482. Result := Add(VectorMake(item));
  1483. end;
  1484. function TVectorList.AddPoint(const item: TAffineVector): Integer;
  1485. begin
  1486. Result := Add(PointMake(item));
  1487. end;
  1488. function TVectorList.AddPoint(const X, Y: Single; const Z: Single = 0): Integer;
  1489. begin
  1490. Result := Add(PointMake(X, Y, Z));
  1491. end;
  1492. function TVectorList.Get(Index: Integer): TGLVector;
  1493. begin
  1494. {$IFOPT R+}
  1495. Assert(Cardinal(Index) < Cardinal(FCount));
  1496. {$ENDIF}
  1497. Result := FList^[Index];
  1498. end;
  1499. procedure TVectorList.Insert(Index: Integer; const Item: TGLVector);
  1500. begin
  1501. {$IFOPT R+}
  1502. Assert(Cardinal(Index) < Cardinal(FCount));
  1503. {$ENDIF}
  1504. if FCount = FCapacity then
  1505. SetCapacity(FCapacity + FGrowthDelta);
  1506. if Index < FCount then
  1507. System.Move(FList[Index], FList[Index + 1],
  1508. (FCount - Index) * SizeOf(TGLVector));
  1509. FList^[Index] := Item;
  1510. Inc(FCount);
  1511. end;
  1512. procedure TVectorList.Put(Index: Integer; const Item: TGLVector);
  1513. begin
  1514. {$IFOPT R+}
  1515. Assert(Cardinal(Index) < Cardinal(FCount));
  1516. {$ENDIF}
  1517. FList^[Index] := Item;
  1518. end;
  1519. procedure TVectorList.SetCapacity(NewCapacity: Integer);
  1520. begin
  1521. inherited;
  1522. FList := PVectorArray(FBaseList);
  1523. end;
  1524. procedure TVectorList.Push(const Val: TGLVector);
  1525. begin
  1526. Add(Val);
  1527. end;
  1528. function TVectorList.Pop: TGLVector;
  1529. begin
  1530. if FCount > 0 then
  1531. begin
  1532. Result := Get(FCount - 1);
  1533. Delete(FCount - 1);
  1534. end
  1535. else
  1536. Result := NullHmgVector;
  1537. end;
  1538. function TVectorList.IndexOf(const item: TGLVector): Integer;
  1539. var
  1540. I: Integer;
  1541. begin
  1542. Result := -1;
  1543. for I := 0 to Count - 1 do
  1544. if VectorEquals(item, FList^[I]) then
  1545. begin
  1546. Result := I;
  1547. Break;
  1548. end;
  1549. end;
  1550. function TVectorList.FindOrAdd(const item: TGLVector): Integer;
  1551. begin
  1552. Result := IndexOf(item);
  1553. if Result < 0 then
  1554. Result := Add(item);
  1555. end;
  1556. function TVectorList.FindOrAddPoint(const item: TAffineVector): Integer;
  1557. var
  1558. ptItem: TGLVector;
  1559. begin
  1560. MakePoint(ptItem, item);
  1561. Result := IndexOf(ptItem);
  1562. if Result < 0 then
  1563. Result := Add(ptItem);
  1564. end;
  1565. procedure TVectorList.Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  1566. begin
  1567. if (list1 is TVectorList) and (list2 is TVectorList) then
  1568. begin
  1569. Assert(list1.Count = list2.Count);
  1570. Capacity := list1.Count;
  1571. FCount := list1.Count;
  1572. VectorArrayLerp(TVectorList(list1).List, TVectorList(list2).List,
  1573. lerpFactor, FCount, List);
  1574. end;
  1575. end;
  1576. // ------------------
  1577. // ------------------ TTexPointList ------------------
  1578. // ------------------
  1579. constructor TTexPointList.Create;
  1580. begin
  1581. FItemSize := SizeOf(TTexPoint);
  1582. inherited Create;
  1583. FGrowthDelta := cDefaultListGrowthDelta;
  1584. end;
  1585. procedure TTexPointList.Assign(Src: TPersistent);
  1586. begin
  1587. if Assigned(Src) then
  1588. begin
  1589. inherited;
  1590. if (Src is TTexPointList) then
  1591. System.Move(TTexPointList(Src).FList^, FList^, FCount * SizeOf(TTexPoint));
  1592. end
  1593. else
  1594. Clear;
  1595. end;
  1596. function TTexPointList.IndexOf(const item: TTexpoint): Integer;
  1597. var
  1598. I: Integer;
  1599. begin
  1600. Result := -1;
  1601. for I := 0 to Count - 1 do
  1602. if TexpointEquals(FList^[I], item) then
  1603. begin
  1604. Result := I;
  1605. Break;
  1606. end;
  1607. end;
  1608. function TTexPointList.FindOrAdd(const item: TTexPoint): Integer;
  1609. begin
  1610. Result := IndexOf(item);
  1611. if Result < 0 then
  1612. Result := Add(item);
  1613. end;
  1614. function TTexPointList.Add(const item: TTexPoint): Integer;
  1615. begin
  1616. Result := FCount;
  1617. if Result = FCapacity then
  1618. SetCapacity(FCapacity + FGrowthDelta);
  1619. FList^[Result] := Item;
  1620. Inc(FCount);
  1621. end;
  1622. function TTexPointList.Add(const item: TVector2f): Integer;
  1623. begin
  1624. Result := FCount;
  1625. if Result = FCapacity then
  1626. SetCapacity(FCapacity + FGrowthDelta);
  1627. FList^[Result] := PTexPoint(@Item)^;
  1628. Inc(FCount);
  1629. end;
  1630. function TTexPointList.Add(const texS, Text: Single): Integer;
  1631. begin
  1632. Result := FCount;
  1633. if Result = FCapacity then
  1634. SetCapacity(FCapacity + FGrowthDelta);
  1635. with FList^[Result] do
  1636. begin
  1637. s := texS;
  1638. t := Text;
  1639. end;
  1640. Inc(FCount);
  1641. end;
  1642. function TTexPointList.Add(const texS, Text: Integer): Integer;
  1643. begin
  1644. Result := FCount;
  1645. if Result = FCapacity then
  1646. SetCapacity(FCapacity + FGrowthDelta);
  1647. with FList^[Result] do
  1648. begin
  1649. s := texS;
  1650. t := Text;
  1651. end;
  1652. Inc(FCount);
  1653. end;
  1654. function TTexPointList.AddNC(const texS, Text: Integer): Integer;
  1655. begin
  1656. Result := FCount;
  1657. with FList^[Result] do
  1658. begin
  1659. s := texS;
  1660. t := Text;
  1661. end;
  1662. Inc(FCount);
  1663. end;
  1664. function TTexPointList.Add(const texST: PIntegerArray): Integer;
  1665. begin
  1666. Result := FCount;
  1667. if Result = FCapacity then
  1668. SetCapacity(FCapacity + FGrowthDelta);
  1669. with FList^[Result] do
  1670. begin
  1671. s := texST^[0];
  1672. t := texST^[1];
  1673. end;
  1674. Inc(FCount);
  1675. end;
  1676. function TTexPointList.AddNC(const texST: PIntegerArray): Integer;
  1677. begin
  1678. Result := FCount;
  1679. with FList^[Result] do
  1680. begin
  1681. s := texST^[0];
  1682. t := texST^[1];
  1683. end;
  1684. Inc(FCount);
  1685. end;
  1686. function TTexPointList.Get(Index: Integer): TTexPoint;
  1687. begin
  1688. {$IFOPT R+}
  1689. Assert(Cardinal(Index) < Cardinal(FCount));
  1690. {$ENDIF}
  1691. Result := FList^[Index];
  1692. end;
  1693. procedure TTexPointList.Insert(Index: Integer; const Item: TTexPoint);
  1694. begin
  1695. {$IFOPT R+}
  1696. Assert(Cardinal(Index) < Cardinal(FCount));
  1697. {$ENDIF}
  1698. if FCount = FCapacity then
  1699. SetCapacity(FCapacity + FGrowthDelta);
  1700. if Index < FCount then
  1701. System.Move(FList[Index], FList[Index + 1],
  1702. (FCount - Index) * SizeOf(TTexPoint));
  1703. FList^[Index] := Item;
  1704. Inc(FCount);
  1705. end;
  1706. procedure TTexPointList.Put(Index: Integer; const Item: TTexPoint);
  1707. begin
  1708. {$IFOPT R+}
  1709. Assert(Cardinal(Index) < Cardinal(FCount));
  1710. {$ENDIF}
  1711. FList^[Index] := Item;
  1712. end;
  1713. procedure TTexPointList.SetCapacity(NewCapacity: Integer);
  1714. begin
  1715. inherited;
  1716. FList := PTexPointArray(FBaseList);
  1717. end;
  1718. procedure TTexPointList.Push(const Val: TTexPoint);
  1719. begin
  1720. Add(Val);
  1721. end;
  1722. function TTexPointList.Pop: TTexPoint;
  1723. begin
  1724. if FCount > 0 then
  1725. begin
  1726. Result := Get(FCount - 1);
  1727. Delete(FCount - 1);
  1728. end
  1729. else
  1730. Result := NullTexPoint;
  1731. end;
  1732. procedure TTexPointList.Translate(const delta: TTexPoint);
  1733. begin
  1734. TexPointArrayAdd(List, delta, FCount, FList);
  1735. end;
  1736. procedure TTexPointList.ScaleAndTranslate(const scale, delta: TTexPoint);
  1737. begin
  1738. TexPointArrayScaleAndAdd(FList, delta, FCount, scale, FList);
  1739. end;
  1740. procedure TTexPointList.ScaleAndTranslate(const scale, delta: TTexPoint; base, nb: Integer);
  1741. var
  1742. p: PTexPointArray;
  1743. begin
  1744. p := @FList[base];
  1745. TexPointArrayScaleAndAdd(p, delta, nb, scale, p);
  1746. end;
  1747. procedure TTexPointList.Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  1748. begin
  1749. if (list1 is TTexPointList) and (list2 is TTexPointList) then
  1750. begin
  1751. Assert(list1.Count = list2.Count);
  1752. Capacity := list1.Count;
  1753. FCount := list1.Count;
  1754. VectorArrayLerp(TTexPointList(list1).List, TTexPointList(list2).List,
  1755. lerpFactor, FCount, List);
  1756. end;
  1757. end;
  1758. // ------------------
  1759. // ------------------ TIntegerList ------------------
  1760. // ------------------
  1761. constructor TIntegerList.Create;
  1762. begin
  1763. FItemSize := SizeOf(Integer);
  1764. inherited Create;
  1765. FGrowthDelta := cDefaultListGrowthDelta;
  1766. end;
  1767. procedure TIntegerList.Assign(Src: TPersistent);
  1768. begin
  1769. if Assigned(Src) then
  1770. begin
  1771. inherited;
  1772. if (Src is TIntegerList) then
  1773. System.Move(TIntegerList(Src).FList^, FList^, FCount * SizeOf(Integer));
  1774. end
  1775. else
  1776. Clear;
  1777. end;
  1778. function TIntegerList.Add(const item: Integer): Integer;
  1779. begin
  1780. Result := FCount;
  1781. if Result = FCapacity then
  1782. SetCapacity(FCapacity + FGrowthDelta);
  1783. FList^[Result] := Item;
  1784. Inc(FCount);
  1785. end;
  1786. function TIntegerList.AddNC(const item: Integer): Integer;
  1787. begin
  1788. Result := FCount;
  1789. FList^[Result] := Item;
  1790. Inc(FCount);
  1791. end;
  1792. procedure TIntegerList.Add(const i1, i2: Integer);
  1793. var
  1794. tmpList : PIntegerArray;
  1795. begin
  1796. Inc(FCount, 2);
  1797. while FCount > FCapacity do
  1798. SetCapacity(FCapacity + FGrowthDelta);
  1799. tmpList := @FList[FCount - 2];
  1800. tmpList^[0] := i1;
  1801. tmpList^[1] := i2;
  1802. end;
  1803. procedure TIntegerList.Add(const i1, i2, i3: Integer);
  1804. var
  1805. tmpList : PIntegerArray;
  1806. begin
  1807. Inc(FCount, 3);
  1808. while FCount > FCapacity do
  1809. SetCapacity(FCapacity + FGrowthDelta);
  1810. tmpList := @FList[FCount - 3];
  1811. tmpList^[0] := i1;
  1812. tmpList^[1] := i2;
  1813. tmpList^[2] := i3;
  1814. end;
  1815. procedure TIntegerList.Add(const AList: TIntegerList);
  1816. begin
  1817. if Assigned(AList) and (AList.Count > 0) then
  1818. begin
  1819. if Count + AList.Count > Capacity then
  1820. Capacity := Count + AList.Count;
  1821. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(Integer));
  1822. Inc(FCount, AList.Count);
  1823. end;
  1824. end;
  1825. function TIntegerList.Get(Index: Integer): Integer;
  1826. begin
  1827. {$IFOPT R+}
  1828. Assert(Cardinal(Index) < Cardinal(FCount));
  1829. {$ENDIF}
  1830. Result := FList^[Index];
  1831. end;
  1832. procedure TIntegerList.Insert(Index: Integer; const Item: Integer);
  1833. begin
  1834. {$IFOPT R+}
  1835. Assert(Cardinal(Index) < Cardinal(FCount));
  1836. {$ENDIF}
  1837. if FCount = FCapacity then
  1838. SetCapacity(FCapacity + FGrowthDelta);
  1839. if Index < FCount then
  1840. System.Move(FList[Index], FList[Index + 1], (FCount - Index) * SizeOf(Integer));
  1841. FList^[Index] := Item;
  1842. Inc(FCount);
  1843. end;
  1844. procedure TIntegerList.Remove(const item: Integer);
  1845. var
  1846. I: Integer;
  1847. begin
  1848. for I := 0 to Count - 1 do
  1849. begin
  1850. if FList^[I] = item then
  1851. begin
  1852. System.Move(FList[I + 1], FList[I], (FCount - 1 - I) * SizeOf(Integer));
  1853. Dec(FCount);
  1854. Break;
  1855. end;
  1856. end;
  1857. end;
  1858. procedure TIntegerList.Put(Index: Integer; const Item: Integer);
  1859. begin
  1860. {$IFOPT R+}
  1861. Assert(Cardinal(Index) < Cardinal(FCount));
  1862. {$ENDIF}
  1863. FList^[Index] := Item;
  1864. end;
  1865. procedure TIntegerList.SetCapacity(NewCapacity: Integer);
  1866. begin
  1867. inherited;
  1868. FList := PIntegerArray(FBaseList);
  1869. end;
  1870. procedure TIntegerList.Push(const Val: Integer);
  1871. begin
  1872. Add(Val);
  1873. end;
  1874. function TIntegerList.Pop: Integer;
  1875. begin
  1876. if FCount > 0 then
  1877. begin
  1878. Result := FList^[FCount - 1];
  1879. Delete(FCount - 1);
  1880. end
  1881. else
  1882. Result := 0;
  1883. end;
  1884. procedure TIntegerList.AddSerie(aBase, aDelta, aCount: Integer);
  1885. var
  1886. tmpList : PInteger;
  1887. I: Integer;
  1888. begin
  1889. if aCount <= 0 then
  1890. Exit;
  1891. AdjustCapacityToAtLeast(Count + aCount);
  1892. tmpList := @FList[Count];
  1893. for I := Count to Count + aCount - 1 do
  1894. begin
  1895. tmpList^ := aBase;
  1896. Inc(tmpList);
  1897. aBase := aBase + aDelta;
  1898. end;
  1899. FCount := Count + aCount;
  1900. end;
  1901. procedure TIntegerList.AddIntegers(const First: PInteger; n: Integer);
  1902. begin
  1903. if n < 1 then
  1904. Exit;
  1905. AdjustCapacityToAtLeast(Count + n);
  1906. System.Move(First^, FList[FCount], n * SizeOf(Integer));
  1907. FCount := FCount + n;
  1908. end;
  1909. procedure TIntegerList.AddIntegers(const aList: TIntegerList);
  1910. begin
  1911. if not Assigned(aList) then
  1912. Exit;
  1913. AddIntegers(@aList.List[0], aList.Count);
  1914. end;
  1915. procedure TIntegerList.AddIntegers(const anArray: array of Integer);
  1916. var
  1917. n: Integer;
  1918. begin
  1919. n := Length(anArray);
  1920. if n > 0 then
  1921. AddIntegers(@anArray[0], n);
  1922. end;
  1923. function IntegerSearch(item: Integer; list: PIntegerVector; Count: Integer): Integer; register; inline;
  1924. var i : integer;
  1925. begin
  1926. result:=-1;
  1927. for i := 0 to Count-1 do begin
  1928. if list^[i]=item then begin
  1929. result:=i;
  1930. break;
  1931. end;
  1932. end;
  1933. end;
  1934. function TIntegerList.IndexOf(item: Integer): Integer; register;
  1935. begin
  1936. Result := IntegerSearch(item, FList, FCount);
  1937. end;
  1938. function TIntegerList.MinInteger: Integer;
  1939. var
  1940. I: Integer;
  1941. locList: PIntegerVector;
  1942. begin
  1943. if FCount > 0 then
  1944. begin
  1945. locList := FList;
  1946. Result := locList^[0];
  1947. for I := 1 to FCount - 1 do
  1948. if locList^[I] < Result then
  1949. Result := locList^[I];
  1950. end
  1951. else
  1952. Result := 0;
  1953. end;
  1954. function TIntegerList.MaxInteger: Integer;
  1955. var
  1956. I: Integer;
  1957. locList: PIntegerVector;
  1958. begin
  1959. if FCount > 0 then
  1960. begin
  1961. locList := FList;
  1962. Result := locList^[0];
  1963. for I := 1 to FCount - 1 do
  1964. if locList^[I] > Result then
  1965. Result := locList^[I];
  1966. end
  1967. else
  1968. Result := 0;
  1969. end;
  1970. procedure IntegerQuickSort(sortList: PIntegerArray; left, right: Integer);
  1971. var
  1972. I, J: Integer;
  1973. p, t: Integer;
  1974. begin
  1975. repeat
  1976. I := left;
  1977. J := right;
  1978. p := sortList^[(left + right) shr 1];
  1979. repeat
  1980. while sortList^[I] < p do
  1981. Inc(I);
  1982. while sortList^[J] > p do
  1983. Dec(J);
  1984. if I <= J then
  1985. begin
  1986. t := sortList^[I];
  1987. sortList^[I] := sortList^[J];
  1988. sortList^[J] := t;
  1989. Inc(I);
  1990. Dec(J);
  1991. end;
  1992. until I > J;
  1993. if left < J then
  1994. IntegerQuickSort(sortList, left, J);
  1995. left := I;
  1996. until I >= right;
  1997. end;
  1998. procedure TIntegerList.Sort;
  1999. begin
  2000. if (FList <> nil) and (Count > 1) then
  2001. IntegerQuickSort(FList, 0, Count - 1);
  2002. end;
  2003. procedure TIntegerList.SortAndRemoveDuplicates;
  2004. var
  2005. I, J, lastVal: Integer;
  2006. localList: PIntegerArray;
  2007. begin
  2008. if (FList <> nil) and (Count > 1) then
  2009. begin
  2010. IntegerQuickSort(FList, 0, Count - 1);
  2011. J := 0;
  2012. localList := FList;
  2013. lastVal := localList^[J];
  2014. for I := 1 to Count - 1 do
  2015. begin
  2016. if localList^[I] <> lastVal then
  2017. begin
  2018. lastVal := localList^[I];
  2019. Inc(J);
  2020. localList^[J] := lastVal;
  2021. end;
  2022. end;
  2023. FCount := J + 1;
  2024. end;
  2025. end;
  2026. function TIntegerList.BinarySearch(const Value: Integer): Integer;
  2027. var
  2028. found: Boolean;
  2029. begin
  2030. Result := BinarySearch(Value, False, found);
  2031. end;
  2032. function TIntegerList.BinarySearch(const Value: Integer; returnBestFit: Boolean; var found: Boolean): Integer;
  2033. var
  2034. Index: Integer;
  2035. min, max, mid: Integer;
  2036. intList: PIntegerArray;
  2037. begin
  2038. // Assume we won't find it
  2039. found := False;
  2040. // If the list is empty, we won't find the sought value!
  2041. if Count = 0 then
  2042. begin
  2043. Result := -1;
  2044. Exit;
  2045. end;
  2046. min := -1; // ONE OFF!
  2047. max := Count; // ONE OFF!
  2048. // We now know that Min and Max AREN'T the values!
  2049. Index := -1;
  2050. intList := List;
  2051. repeat
  2052. // Find the middle of the current scope
  2053. mid := (min + max) shr 1;
  2054. // Reduce the search scope by half
  2055. if intList^[mid] <= Value then
  2056. begin
  2057. // Is this the one?
  2058. if intList^[mid] = Value then
  2059. begin
  2060. Index := mid;
  2061. found := True;
  2062. Break;
  2063. end
  2064. else
  2065. min := mid;
  2066. end
  2067. else
  2068. max := mid;
  2069. until min + 1 = max;
  2070. if returnBestFit then
  2071. begin
  2072. if Index >= 0 then
  2073. Result := Index
  2074. else
  2075. Result := min;
  2076. end
  2077. else
  2078. Result := Index;
  2079. end;
  2080. function TIntegerList.AddSorted(const Value: Integer; const ignoreDuplicates: Boolean = False): Integer;
  2081. var
  2082. Index: Integer;
  2083. found: Boolean;
  2084. begin
  2085. Index := BinarySearch(Value, True, found);
  2086. if ignoreDuplicates and Found then
  2087. Result := -1
  2088. else
  2089. begin
  2090. Insert(Index + 1, Value);
  2091. Result := Index + 1;
  2092. end;
  2093. end;
  2094. procedure TIntegerList.RemoveSorted(const Value: Integer);
  2095. var
  2096. Index: Integer;
  2097. begin
  2098. Index := BinarySearch(Value);
  2099. if Index >= 0 then
  2100. Delete(Index);
  2101. end;
  2102. procedure TIntegerList.Offset(delta: Integer);
  2103. var
  2104. I: Integer;
  2105. locList: PIntegerArray;
  2106. begin
  2107. locList := FList;
  2108. for I := 0 to FCount - 1 do
  2109. locList^[I] := locList^[I] + delta;
  2110. end;
  2111. procedure TIntegerList.Offset(delta: Integer; const base, nb: Integer);
  2112. var
  2113. I: Integer;
  2114. locList: PIntegerArray;
  2115. begin
  2116. locList := FList;
  2117. for I := base to base + nb - 1 do
  2118. locList^[I] := locList^[I] + delta;
  2119. end;
  2120. // ------------------
  2121. // ------------------ TSingleList ------------------
  2122. // ------------------
  2123. constructor TSingleList.Create;
  2124. begin
  2125. FItemSize := SizeOf(Single);
  2126. inherited Create;
  2127. FGrowthDelta := cDefaultListGrowthDelta;
  2128. end;
  2129. procedure TSingleList.Assign(Src: TPersistent);
  2130. begin
  2131. if Assigned(Src) then
  2132. begin
  2133. inherited;
  2134. if (Src is TSingleList) then
  2135. System.Move(TSingleList(Src).FList^, FList^, FCount * SizeOf(Single));
  2136. end
  2137. else
  2138. Clear;
  2139. end;
  2140. function TSingleList.Add(const item: Single): Integer;
  2141. begin
  2142. Result := FCount;
  2143. if Result = FCapacity then
  2144. SetCapacity(FCapacity + FGrowthDelta);
  2145. FList^[Result] := Item;
  2146. Inc(FCount);
  2147. end;
  2148. procedure TSingleList.Add(const i1, i2: Single);
  2149. var
  2150. tmpList : PSingleArray;
  2151. begin
  2152. Inc(FCount, 2);
  2153. while FCount > FCapacity do
  2154. SetCapacity(FCapacity + FGrowthDelta);
  2155. tmpList := @FList[FCount - 2];
  2156. tmpList^[0] := i1;
  2157. tmpList^[1] := i2;
  2158. end;
  2159. procedure TSingleList.AddSingles(const First: PSingle; n: Integer);
  2160. begin
  2161. if n < 1 then
  2162. Exit;
  2163. AdjustCapacityToAtLeast(Count + n);
  2164. System.Move(First^, FList[FCount], n * SizeOf(Single));
  2165. FCount := FCount + n;
  2166. end;
  2167. procedure TSingleList.AddSingles(const anArray: array of Single);
  2168. var
  2169. n: Integer;
  2170. begin
  2171. n := Length(anArray);
  2172. if n > 0 then
  2173. AddSingles(@anArray[0], n);
  2174. end;
  2175. function TSingleList.Get(Index: Integer): Single;
  2176. begin
  2177. {$IFOPT R+}
  2178. Assert(Cardinal(Index) < Cardinal(FCount));
  2179. {$ENDIF}
  2180. Result := FList^[Index];
  2181. end;
  2182. procedure TSingleList.Insert(Index: Integer; const Item: Single);
  2183. begin
  2184. {$IFOPT R+}
  2185. Assert(Cardinal(Index) < Cardinal(FCount));
  2186. {$ENDIF}
  2187. if FCount = FCapacity then
  2188. SetCapacity(FCapacity + FGrowthDelta);
  2189. if Index < FCount then
  2190. System.Move(FList[Index], FList[Index + 1],
  2191. (FCount - Index) * SizeOf(Single));
  2192. FList^[Index] := Item;
  2193. Inc(FCount);
  2194. end;
  2195. procedure TSingleList.Put(Index: Integer; const Item: Single);
  2196. begin
  2197. {$IFOPT R+}
  2198. Assert(Cardinal(Index) < Cardinal(FCount));
  2199. {$ENDIF}
  2200. FList^[Index] := Item;
  2201. end;
  2202. procedure TSingleList.SetCapacity(NewCapacity: Integer);
  2203. begin
  2204. inherited;
  2205. FList := PSingleArrayList(FBaseList);
  2206. end;
  2207. procedure TSingleList.Push(const Val: Single);
  2208. begin
  2209. Add(Val);
  2210. end;
  2211. function TSingleList.Pop: Single;
  2212. begin
  2213. if FCount > 0 then
  2214. begin
  2215. Result := Get(FCount - 1);
  2216. Delete(FCount - 1);
  2217. end
  2218. else
  2219. Result := 0;
  2220. end;
  2221. procedure TSingleList.AddSerie(aBase, aDelta: Single; aCount: Integer);
  2222. var
  2223. tmpList : PSingle;
  2224. I: Integer;
  2225. begin
  2226. if aCount <= 0 then
  2227. Exit;
  2228. AdjustCapacityToAtLeast(Count + aCount);
  2229. tmpList := @FList[Count];
  2230. for I := Count to Count + aCount - 1 do
  2231. begin
  2232. tmpList^ := aBase;
  2233. Inc(tmpList);
  2234. aBase := aBase + aDelta;
  2235. end;
  2236. FCount := Count + aCount;
  2237. end;
  2238. procedure TSingleList.Offset(delta: Single);
  2239. begin
  2240. OffsetFloatArray(PFloatVector(FList), FCount, delta);
  2241. end;
  2242. procedure TSingleList.Offset(const delta: TSingleList);
  2243. begin
  2244. if FCount = delta.FCount then
  2245. OffsetFloatArray(PFloatVector(FList), PFloatVector(delta.FList), FCount)
  2246. else
  2247. raise Exception.Create('SingleList count do not match');
  2248. end;
  2249. procedure TSingleList.Scale(factor: Single);
  2250. begin
  2251. ScaleFloatArray(PFloatVector(FList), FCount, factor);
  2252. end;
  2253. procedure TSingleList.Sqr;
  2254. var
  2255. I: Integer;
  2256. locList: PSingleArrayList;
  2257. begin
  2258. locList := FList;
  2259. for I := 0 to Count - 1 do
  2260. locList^[I] := locList^[I] * locList^[I];
  2261. end;
  2262. procedure TSingleList.Sqrt;
  2263. var
  2264. I: Integer;
  2265. locList: PSingleArrayList;
  2266. begin
  2267. locList := FList;
  2268. for I := 0 to Count - 1 do
  2269. locList^[I] := System.Sqrt(locList^[I]);
  2270. end;
  2271. function TSingleList.Sum: Single;
  2272. var
  2273. i: Integer;
  2274. begin
  2275. Result := 0;
  2276. for i := 0 to FCount-1 do
  2277. Result := Result + FList^[i];
  2278. end;
  2279. function TSingleList.Min: Single;
  2280. var
  2281. I: Integer;
  2282. locList: PSingleArrayList;
  2283. begin
  2284. if FCount > 0 then
  2285. begin
  2286. locList := FList;
  2287. Result := locList^[0];
  2288. for I := 1 to FCount - 1 do
  2289. if locList^[I] < Result then
  2290. Result := locList^[I];
  2291. end
  2292. else
  2293. Result := 0;
  2294. end;
  2295. function TSingleList.Max: Single;
  2296. var
  2297. I: Integer;
  2298. locList: PSingleArrayList;
  2299. begin
  2300. if FCount > 0 then
  2301. begin
  2302. locList := FList;
  2303. Result := locList^[0];
  2304. for I := 1 to FCount - 1 do
  2305. if locList^[I] > Result then
  2306. Result := locList^[I];
  2307. end
  2308. else
  2309. Result := 0;
  2310. end;
  2311. // ------------------
  2312. // ------------------ TByteList ------------------
  2313. // ------------------
  2314. constructor TByteList.Create;
  2315. begin
  2316. FItemSize := SizeOf(Byte);
  2317. inherited Create;
  2318. FGrowthDelta := cDefaultListGrowthDelta;
  2319. end;
  2320. procedure TByteList.Assign(Src: TPersistent);
  2321. begin
  2322. if Assigned(Src) then
  2323. begin
  2324. inherited;
  2325. if (Src is TByteList) then
  2326. System.Move(TByteList(Src).FList^, FList^, FCount * SizeOf(Byte));
  2327. end
  2328. else
  2329. Clear;
  2330. end;
  2331. function TByteList.Add(const item: Byte): Integer;
  2332. begin
  2333. Result := FCount;
  2334. if Result = FCapacity then
  2335. SetCapacity(FCapacity + FGrowthDelta);
  2336. FList^[Result] := Item;
  2337. Inc(FCount);
  2338. end;
  2339. function TByteList.Get(Index: Integer): Byte;
  2340. begin
  2341. {$IFOPT R+}
  2342. Assert(Cardinal(Index) < Cardinal(FCount));
  2343. {$ENDIF}
  2344. Result := FList^[Index];
  2345. end;
  2346. procedure TByteList.Insert(Index: Integer; const Item: Byte);
  2347. begin
  2348. {$IFOPT R+}
  2349. Assert(Cardinal(Index) < Cardinal(FCount));
  2350. {$ENDIF}
  2351. if FCount = FCapacity then
  2352. SetCapacity(FCapacity + FGrowthDelta);
  2353. if Index < FCount then
  2354. System.Move(FList[Index], FList[Index + 1],
  2355. (FCount - Index) * SizeOf(Byte));
  2356. FList^[Index] := Item;
  2357. Inc(FCount);
  2358. end;
  2359. procedure TByteList.Put(Index: Integer; const Item: Byte);
  2360. begin
  2361. {$IFOPT R+}
  2362. Assert(Cardinal(Index) < Cardinal(FCount));
  2363. {$ENDIF}
  2364. FList^[Index] := Item;
  2365. end;
  2366. procedure TByteList.SetCapacity(NewCapacity: Integer);
  2367. begin
  2368. inherited;
  2369. FList := PByteArray(FBaseList);
  2370. end;
  2371. // ------------------
  2372. // ------------------ TDoubleList ------------------
  2373. // ------------------
  2374. constructor TDoubleList.Create;
  2375. begin
  2376. FItemSize := SizeOf(Double);
  2377. inherited Create;
  2378. FGrowthDelta := cDefaultListGrowthDelta;
  2379. end;
  2380. procedure TDoubleList.Assign(Src: TPersistent);
  2381. begin
  2382. if Assigned(Src) then
  2383. begin
  2384. inherited;
  2385. if (Src is TDoubleList) then
  2386. System.Move(TDoubleList(Src).FList^, FList^, FCount * SizeOf(Double));
  2387. end
  2388. else
  2389. Clear;
  2390. end;
  2391. function TDoubleList.Add(const item: Double): Integer;
  2392. begin
  2393. Result := FCount;
  2394. if Result = FCapacity then
  2395. SetCapacity(FCapacity + FGrowthDelta);
  2396. FList^[Result] := Item;
  2397. Inc(FCount);
  2398. end;
  2399. function TDoubleList.Get(Index: Integer): Double;
  2400. begin
  2401. {$IFOPT R+}
  2402. Assert(Cardinal(Index) < Cardinal(FCount));
  2403. {$ENDIF}
  2404. Result := FList^[Index];
  2405. end;
  2406. procedure TDoubleList.Insert(Index: Integer; const Item: Double);
  2407. begin
  2408. {$IFOPT R+}
  2409. Assert(Cardinal(Index) < Cardinal(FCount));
  2410. {$ENDIF}
  2411. if FCount = FCapacity then
  2412. SetCapacity(FCapacity + FGrowthDelta);
  2413. if Index < FCount then
  2414. System.Move(FList[Index], FList[Index + 1],
  2415. (FCount - Index) * SizeOf(Double));
  2416. FList^[Index] := Item;
  2417. Inc(FCount);
  2418. end;
  2419. procedure TDoubleList.Put(Index: Integer; const Item: Double);
  2420. begin
  2421. {$IFOPT R+}
  2422. Assert(Cardinal(Index) < Cardinal(FCount));
  2423. {$ENDIF}
  2424. FList^[Index] := Item;
  2425. end;
  2426. procedure TDoubleList.SetCapacity(NewCapacity: Integer);
  2427. begin
  2428. inherited;
  2429. FList := PDoubleArrayList(FBaseList);
  2430. end;
  2431. procedure TDoubleList.Push(const Val: Double);
  2432. begin
  2433. Add(Val);
  2434. end;
  2435. function TDoubleList.Pop: Double;
  2436. begin
  2437. if FCount > 0 then
  2438. begin
  2439. Result := Get(FCount - 1);
  2440. Delete(FCount - 1);
  2441. end
  2442. else
  2443. Result := 0;
  2444. end;
  2445. procedure TDoubleList.AddSerie(aBase, aDelta: Double; aCount: Integer);
  2446. var
  2447. tmpList: PDouble;
  2448. I: Integer;
  2449. begin
  2450. if aCount <= 0 then
  2451. Exit;
  2452. AdjustCapacityToAtLeast(Count + aCount);
  2453. tmpList := @FList[Count];
  2454. for I := Count to Count + aCount - 1 do
  2455. begin
  2456. tmpList^ := aBase;
  2457. Inc(tmpList);
  2458. aBase := aBase + aDelta;
  2459. end;
  2460. FCount := Count + aCount;
  2461. end;
  2462. procedure TDoubleList.Offset(delta: Double);
  2463. var
  2464. I: Integer;
  2465. begin
  2466. for I := 0 to Count - 1 do
  2467. FList^[I] := FList^[I] + delta;
  2468. end;
  2469. procedure TDoubleList.Offset(const delta: TDoubleList);
  2470. var
  2471. I: Integer;
  2472. begin
  2473. if FCount = delta.FCount then
  2474. for I := 0 to Count - 1 do
  2475. FList^[I] := FList^[I] + delta[I]
  2476. else
  2477. raise Exception.Create('DoubleList count do not match');
  2478. end;
  2479. procedure TDoubleList.Scale(factor: Double);
  2480. var
  2481. I: Integer;
  2482. begin
  2483. for I := 0 to Count - 1 do
  2484. FList^[I] := FList^[I] * factor;
  2485. end;
  2486. procedure TDoubleList.Sqr;
  2487. var
  2488. I: Integer;
  2489. locList: PDoubleArrayList;
  2490. begin
  2491. locList := FList;
  2492. for I := 0 to Count - 1 do
  2493. locList^[I] := locList^[I] * locList^[I];
  2494. end;
  2495. procedure TDoubleList.Sqrt;
  2496. var
  2497. I: Integer;
  2498. locList: PDoubleArrayList;
  2499. begin
  2500. locList := FList;
  2501. for I := 0 to Count - 1 do
  2502. locList^[I] := System.Sqrt(locList^[I]);
  2503. end;
  2504. function TDoubleList.Sum: Double;
  2505. var
  2506. i: Integer;
  2507. begin
  2508. Result := 0;
  2509. for i := 0 to FCount-1 do
  2510. Result := Result + FList^[i];
  2511. end;
  2512. function TDoubleList.Min: Single;
  2513. var
  2514. I: Integer;
  2515. locList: PDoubleArrayList;
  2516. begin
  2517. if FCount > 0 then
  2518. begin
  2519. locList := FList;
  2520. Result := locList^[0];
  2521. for I := 1 to FCount - 1 do
  2522. if locList^[I] < Result then
  2523. Result := locList^[I];
  2524. end
  2525. else
  2526. Result := 0;
  2527. end;
  2528. function TDoubleList.Max: Single;
  2529. var
  2530. I: Integer;
  2531. locList: PDoubleArrayList;
  2532. begin
  2533. if FCount > 0 then
  2534. begin
  2535. locList := FList;
  2536. Result := locList^[0];
  2537. for I := 1 to FCount - 1 do
  2538. if locList^[I] > Result then
  2539. Result := locList^[I];
  2540. end
  2541. else
  2542. Result := 0;
  2543. end;
  2544. // ------------------
  2545. // ------------------ TQuaternionList ------------------
  2546. // ------------------
  2547. constructor TQuaternionList.Create;
  2548. begin
  2549. FItemSize := SizeOf(TQuaternion);
  2550. inherited Create;
  2551. FGrowthDelta := cDefaultListGrowthDelta;
  2552. end;
  2553. procedure TQuaternionList.Assign(Src: TPersistent);
  2554. begin
  2555. if Assigned(Src) then
  2556. begin
  2557. inherited;
  2558. if (Src is TQuaternionList) then
  2559. System.Move(TQuaternionList(Src).FList^, FList^, FCount * SizeOf(TQuaternion));
  2560. end
  2561. else
  2562. Clear;
  2563. end;
  2564. function TQuaternionList.Add(const item: TQuaternion): Integer;
  2565. begin
  2566. Result := FCount;
  2567. if Result = FCapacity then
  2568. SetCapacity(FCapacity + FGrowthDelta);
  2569. FList^[Result] := Item;
  2570. Inc(FCount);
  2571. end;
  2572. function TQuaternionList.Add(const item: TAffineVector; w: Single): Integer;
  2573. begin
  2574. Result := Add(QuaternionMake([item.X, item.Y, item.Z], w));
  2575. end;
  2576. function TQuaternionList.Add(const X, Y, Z, w: Single): Integer;
  2577. begin
  2578. Result := Add(QuaternionMake([X, Y, Z], w));
  2579. end;
  2580. function TQuaternionList.Get(Index: Integer): TQuaternion;
  2581. begin
  2582. {$IFOPT R+}
  2583. Assert(Cardinal(Index) < Cardinal(FCount));
  2584. {$ENDIF}
  2585. Result := FList^[Index];
  2586. end;
  2587. procedure TQuaternionList.Insert(Index: Integer; const Item: TQuaternion);
  2588. begin
  2589. {$IFOPT R+}
  2590. Assert(Cardinal(Index) < Cardinal(FCount));
  2591. {$ENDIF}
  2592. if FCount = FCapacity then
  2593. SetCapacity(FCapacity + FGrowthDelta);
  2594. if Index < FCount then
  2595. System.Move(FList[Index], FList[Index + 1],
  2596. (FCount - Index) * SizeOf(TQuaternion));
  2597. FList^[Index] := Item;
  2598. Inc(FCount);
  2599. end;
  2600. procedure TQuaternionList.Put(Index: Integer; const Item: TQuaternion);
  2601. begin
  2602. {$IFOPT R+}
  2603. Assert(Cardinal(Index) < Cardinal(FCount));
  2604. {$ENDIF}
  2605. FList^[Index] := Item;
  2606. end;
  2607. procedure TQuaternionList.SetCapacity(NewCapacity: Integer);
  2608. begin
  2609. inherited;
  2610. FList := PQuaternionArray(FBaseList);
  2611. end;
  2612. procedure TQuaternionList.Push(const Val: TQuaternion);
  2613. begin
  2614. Add(Val);
  2615. end;
  2616. function TQuaternionList.Pop: TQuaternion;
  2617. begin
  2618. if FCount > 0 then
  2619. begin
  2620. Result := Get(FCount - 1);
  2621. Delete(FCount - 1);
  2622. end
  2623. else
  2624. Result := IdentityQuaternion;
  2625. end;
  2626. function TQuaternionList.IndexOf(const item: TQuaternion): Integer;
  2627. var
  2628. I: Integer;
  2629. curItem: PQuaternion;
  2630. begin
  2631. for I := 0 to Count - 1 do
  2632. begin
  2633. curItem := @FList[I];
  2634. if (item.RealPart = curItem^.RealPart) and VectorEquals(item.ImagPart, curItem^.ImagPart) then
  2635. begin
  2636. Result := I;
  2637. Exit;
  2638. end;
  2639. end;
  2640. Result := -1;
  2641. end;
  2642. function TQuaternionList.FindOrAdd(const item: TQuaternion): Integer;
  2643. begin
  2644. Result := IndexOf(item);
  2645. if Result < 0 then
  2646. Result := Add(item);
  2647. end;
  2648. procedure TQuaternionList.Lerp(const list1, list2: TBaseVectorList; lerpFactor: Single);
  2649. var
  2650. I: Integer;
  2651. begin
  2652. if (list1 is TQuaternionList) and (list2 is TQuaternionList) then
  2653. begin
  2654. Assert(list1.Count = list2.Count);
  2655. Capacity := list1.Count;
  2656. FCount := list1.Count;
  2657. for I := 0 to FCount - 1 do
  2658. Put(I, QuaternionSlerp(TQuaternionList(list1)[I], TQuaternionList(list2)[I], lerpFactor));
  2659. end;
  2660. end;
  2661. procedure TQuaternionList.Combine(const list2: TBaseVectorList; factor: Single);
  2662. procedure CombineQuaternion(var q1: TQuaternion; const q2: TQuaternion; factor: Single);
  2663. begin
  2664. q1 := QuaternionMultiply(q1, QuaternionSlerp(IdentityQuaternion, q2, factor));
  2665. end;
  2666. var
  2667. I: Integer;
  2668. begin
  2669. Assert(list2.Count >= Count);
  2670. if list2 is TQuaternionList then
  2671. begin
  2672. for I := 0 to Count - 1 do
  2673. begin
  2674. CombineQuaternion(PQuaternion(ItemAddress[I])^,
  2675. PQuaternion(list2.ItemAddress[I])^,
  2676. factor);
  2677. end;
  2678. end
  2679. else
  2680. inherited;
  2681. end;
  2682. // ------------------
  2683. // ------------------ T4ByteList ------------------
  2684. // ------------------
  2685. constructor T4ByteList.Create;
  2686. begin
  2687. FItemSize := SizeOf(T4ByteList);
  2688. inherited Create;
  2689. FGrowthDelta := cDefaultListGrowthDelta;
  2690. end;
  2691. procedure T4ByteList.Assign(Src: TPersistent);
  2692. begin
  2693. if Assigned(Src) then
  2694. begin
  2695. inherited;
  2696. if (Src is T4ByteList) then
  2697. System.Move(T4ByteList(Src).FList^, FList^, FCount * SizeOf(T4ByteData));
  2698. end
  2699. else
  2700. Clear;
  2701. end;
  2702. function T4ByteList.Add(const item: T4ByteData): Integer;
  2703. begin
  2704. Result := FCount;
  2705. if Result = FCapacity then
  2706. SetCapacity(FCapacity + FGrowthDelta);
  2707. FList^[Result] := Item;
  2708. Inc(FCount);
  2709. Inc(FRevision);
  2710. end;
  2711. procedure T4ByteList.Add(const i1: Single);
  2712. var
  2713. tmpList: PSingle;
  2714. begin
  2715. Inc(FCount);
  2716. if FCount >= FCapacity then
  2717. SetCapacity(FCapacity + FGrowthDelta);
  2718. tmpList := @FList[FCount - 1];
  2719. tmpList^ := i1;
  2720. Inc(FRevision);
  2721. end;
  2722. procedure T4ByteList.Add(const i1, i2: Single);
  2723. var
  2724. tmpList: PSingleArray;
  2725. begin
  2726. Inc(FCount, 2);
  2727. while FCount > FCapacity do
  2728. SetCapacity(FCapacity + FGrowthDelta);
  2729. tmpList := @FList[FCount - 2];
  2730. tmpList^[0] := i1;
  2731. tmpList^[1] := i2;
  2732. Inc(FRevision);
  2733. end;
  2734. procedure T4ByteList.Add(const i1, i2, i3: Single);
  2735. var
  2736. tmpList: PSingleArray;
  2737. begin
  2738. Inc(FCount, 3);
  2739. while FCount > FCapacity do
  2740. SetCapacity(FCapacity + FGrowthDelta);
  2741. tmpList := @FList[FCount - 3];
  2742. tmpList^[0] := i1;
  2743. tmpList^[1] := i2;
  2744. tmpList^[2] := i3;
  2745. Inc(FRevision);
  2746. end;
  2747. procedure T4ByteList.Add(const i1, i2, i3, i4: Single);
  2748. var
  2749. tmpList: PSingleArray;
  2750. begin
  2751. Inc(FCount, 4);
  2752. while FCount > FCapacity do
  2753. SetCapacity(FCapacity + FGrowthDelta);
  2754. tmpList := @FList[FCount - 4];
  2755. tmpList^[0] := i1;
  2756. tmpList^[1] := i2;
  2757. tmpList^[2] := i3;
  2758. tmpList^[3] := i4;
  2759. Inc(FRevision);
  2760. end;
  2761. procedure T4ByteList.Add(const i1: Integer);
  2762. var
  2763. tmpList: PInteger;
  2764. begin
  2765. Inc(FCount);
  2766. while FCount > FCapacity do
  2767. SetCapacity(FCapacity + FGrowthDelta);
  2768. tmpList := @FList[FCount - 1];
  2769. tmpList^ := i1;
  2770. Inc(FRevision);
  2771. end;
  2772. procedure T4ByteList.Add(const i1, i2: Integer);
  2773. var
  2774. tmpList: PIntegerArray;
  2775. begin
  2776. Inc(FCount, 2);
  2777. while FCount > FCapacity do
  2778. SetCapacity(FCapacity + FGrowthDelta);
  2779. tmpList := @FList[FCount - 2];
  2780. tmpList^[0] := i1;
  2781. tmpList^[1] := i2;
  2782. Inc(FRevision);
  2783. end;
  2784. procedure T4ByteList.Add(const i1, i2, i3: Integer);
  2785. var
  2786. tmpList: PIntegerArray;
  2787. begin
  2788. Inc(FCount, 3);
  2789. while FCount > FCapacity do
  2790. SetCapacity(FCapacity + FGrowthDelta);
  2791. tmpList := @FList[FCount - 3];
  2792. tmpList^[0] := i1;
  2793. tmpList^[1] := i2;
  2794. tmpList^[2] := i3;
  2795. Inc(FRevision);
  2796. end;
  2797. procedure T4ByteList.Add(const i1, i2, i3, i4: Integer);
  2798. var
  2799. tmpList: PIntegerArray;
  2800. begin
  2801. Inc(FCount, 4);
  2802. while FCount > FCapacity do
  2803. SetCapacity(FCapacity + FGrowthDelta);
  2804. tmpList := @FList[FCount - 4];
  2805. tmpList^[0] := i1;
  2806. tmpList^[1] := i2;
  2807. tmpList^[2] := i3;
  2808. tmpList^[3] := i4;
  2809. Inc(FRevision);
  2810. end;
  2811. procedure T4ByteList.Add(const i1: Cardinal);
  2812. var
  2813. tmpList: PLongWord;
  2814. begin
  2815. Inc(FCount);
  2816. while FCount > FCapacity do
  2817. SetCapacity(FCapacity + FGrowthDelta);
  2818. tmpList := @FList[FCount - 1];
  2819. tmpList^ := i1;
  2820. Inc(FRevision);
  2821. end;
  2822. procedure T4ByteList.Add(const i1, i2: Cardinal);
  2823. var
  2824. tmpList: PLongWordArray;
  2825. begin
  2826. Inc(FCount, 2);
  2827. while FCount > FCapacity do
  2828. SetCapacity(FCapacity + FGrowthDelta);
  2829. tmpList := @FList[FCount - 2];
  2830. tmpList^[0] := i1;
  2831. tmpList^[1] := i2;
  2832. Inc(FRevision);
  2833. end;
  2834. procedure T4ByteList.Add(const i1, i2, i3: Cardinal);
  2835. var
  2836. tmpList: PLongWordArray;
  2837. begin
  2838. Inc(FCount, 3);
  2839. while FCount > FCapacity do
  2840. SetCapacity(FCapacity + FGrowthDelta);
  2841. tmpList := @FList[FCount - 3];
  2842. tmpList^[0] := i1;
  2843. tmpList^[1] := i2;
  2844. tmpList^[2] := i3;
  2845. Inc(FRevision);
  2846. end;
  2847. procedure T4ByteList.Add(const i1, i2, i3, i4: Cardinal);
  2848. var
  2849. tmpList: PLongWordArray;
  2850. begin
  2851. Inc(FCount, 4);
  2852. while FCount > FCapacity do
  2853. SetCapacity(FCapacity + FGrowthDelta);
  2854. tmpList := @FList[FCount - 4];
  2855. tmpList^[0] := i1;
  2856. tmpList^[1] := i2;
  2857. tmpList^[2] := i3;
  2858. tmpList^[3] := i4;
  2859. Inc(FRevision);
  2860. end;
  2861. procedure T4ByteList.Add(const AList: T4ByteList);
  2862. begin
  2863. if Assigned(AList) and (AList.Count > 0) then
  2864. begin
  2865. if Count + AList.Count > Capacity then
  2866. Capacity := Count + AList.Count;
  2867. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(T4ByteData));
  2868. Inc(FCount, AList.Count);
  2869. Inc(FRevision);
  2870. end;
  2871. end;
  2872. function T4ByteList.Get(Index: Integer): T4ByteData;
  2873. begin
  2874. {$IFOPT R+}
  2875. Assert(Cardinal(Index) < Cardinal(FCount));
  2876. {$ENDIF}
  2877. Result := FList^[Index];
  2878. end;
  2879. procedure T4ByteList.Insert(Index: Integer; const Item: T4ByteData);
  2880. begin
  2881. {$IFOPT R+}
  2882. Assert(Cardinal(Index) < Cardinal(FCount));
  2883. {$ENDIF}
  2884. if FCount = FCapacity then
  2885. SetCapacity(FCapacity + FGrowthDelta);
  2886. if Index < FCount then
  2887. System.Move(FList[Index], FList[Index + 1],
  2888. (FCount - Index) * SizeOf(T4ByteData));
  2889. FList^[Index] := Item;
  2890. Inc(FCount);
  2891. Inc(FRevision);
  2892. end;
  2893. procedure T4ByteList.Put(Index: Integer; const Item: T4ByteData);
  2894. begin
  2895. {$IFOPT R+}
  2896. Assert(Cardinal(Index) < Cardinal(FCount));
  2897. {$ENDIF}
  2898. FList^[Index] := Item;
  2899. INc(FRevision);
  2900. end;
  2901. procedure T4ByteList.SetCapacity(NewCapacity: Integer);
  2902. begin
  2903. inherited;
  2904. FList := P4ByteArrayList(FBaseList);
  2905. end;
  2906. procedure T4ByteList.Push(const Val: T4ByteData);
  2907. begin
  2908. Add(Val);
  2909. end;
  2910. function T4ByteList.Pop: T4ByteData;
  2911. const
  2912. Zero : T4ByteData = ( Int: (Value:0) );
  2913. begin
  2914. if FCount > 0 then
  2915. begin
  2916. Result := Get(FCount - 1);
  2917. Delete(FCount - 1);
  2918. end
  2919. else
  2920. Result := Zero;
  2921. end;
  2922. // ------------------
  2923. // ------------------ TLongWordList ------------------
  2924. // ------------------
  2925. constructor TLongWordList.Create;
  2926. begin
  2927. FItemSize := SizeOf(LongWord);
  2928. inherited Create;
  2929. FGrowthDelta := cDefaultListGrowthDelta;
  2930. end;
  2931. procedure TLongWordList.Assign(Src: TPersistent);
  2932. begin
  2933. if Assigned(Src) then
  2934. begin
  2935. inherited;
  2936. if (Src is TLongWordList) then
  2937. System.Move(TLongWordList(Src).FList^, FList^, FCount * SizeOf(LongWord));
  2938. end
  2939. else
  2940. Clear;
  2941. end;
  2942. function TLongWordList.Add(const item: LongWord): Integer;
  2943. begin
  2944. Result := FCount;
  2945. if Result = FCapacity then
  2946. SetCapacity(FCapacity + FGrowthDelta);
  2947. FList^[Result] := Item;
  2948. Inc(FCount);
  2949. end;
  2950. function TLongWordList.AddNC(const item: LongWord): Integer;
  2951. begin
  2952. Result := FCount;
  2953. FList^[Result] := Item;
  2954. Inc(FCount);
  2955. end;
  2956. procedure TLongWordList.Add(const i1, i2: LongWord);
  2957. var
  2958. tmpList : PLongWordArray;
  2959. begin
  2960. Inc(FCount, 2);
  2961. while FCount > FCapacity do
  2962. SetCapacity(FCapacity + FGrowthDelta);
  2963. tmpList := @FList[FCount - 2];
  2964. tmpList^[0] := i1;
  2965. tmpList^[1] := i2;
  2966. end;
  2967. procedure TLongWordList.Add(const i1, i2, i3: LongWord);
  2968. var
  2969. tmpList : PLongWordArray;
  2970. begin
  2971. Inc(FCount, 3);
  2972. while FCount > FCapacity do
  2973. SetCapacity(FCapacity + FGrowthDelta);
  2974. tmpList := @FList[FCount - 3];
  2975. tmpList^[0] := i1;
  2976. tmpList^[1] := i2;
  2977. tmpList^[2] := i3;
  2978. end;
  2979. procedure TLongWordList.Add(const AList: TLongWordList);
  2980. begin
  2981. if Assigned(AList) and (AList.Count > 0) then
  2982. begin
  2983. if Count + AList.Count > Capacity then
  2984. Capacity := Count + AList.Count;
  2985. System.Move(AList.FList[0], FList[Count], AList.Count * SizeOf(LongWord));
  2986. Inc(FCount, AList.Count);
  2987. end;
  2988. end;
  2989. function TLongWordList.Get(Index: Integer): LongWord;
  2990. begin
  2991. {$IFOPT R+}
  2992. Assert(Cardinal(Index) < Cardinal(FCount));
  2993. {$ENDIF}
  2994. Result := FList^[Index];
  2995. end;
  2996. procedure TLongWordList.Insert(Index: Integer; const Item: LongWord);
  2997. begin
  2998. {$IFOPT R+}
  2999. Assert(Cardinal(Index) < Cardinal(FCount));
  3000. {$ENDIF}
  3001. if FCount = FCapacity then
  3002. SetCapacity(FCapacity + FGrowthDelta);
  3003. if Index < FCount then
  3004. System.Move(FList[Index], FList[Index + 1], (FCount - Index) * SizeOf(LongWord));
  3005. FList^[Index] := Item;
  3006. Inc(FCount);
  3007. end;
  3008. procedure TLongWordList.Remove(const item: LongWord);
  3009. var
  3010. I: Integer;
  3011. begin
  3012. for I := 0 to Count - 1 do
  3013. begin
  3014. if FList^[I] = item then
  3015. begin
  3016. System.Move(FList[I + 1], FList[I], (FCount - 1 - I) * SizeOf(LongWord));
  3017. Dec(FCount);
  3018. Break;
  3019. end;
  3020. end;
  3021. end;
  3022. procedure TLongWordList.Put(Index: Integer; const Item: LongWord);
  3023. begin
  3024. {$IFOPT R+}
  3025. Assert(Cardinal(Index) < Cardinal(FCount));
  3026. {$ENDIF}
  3027. FList^[Index] := Item;
  3028. end;
  3029. procedure TLongWordList.SetCapacity(NewCapacity: Integer);
  3030. begin
  3031. inherited;
  3032. FList := PLongWordArray(FBaseList);
  3033. end;
  3034. procedure TLongWordList.Push(const Val: LongWord);
  3035. begin
  3036. Add(Val);
  3037. end;
  3038. function TLongWordList.Pop: LongWord;
  3039. begin
  3040. if FCount > 0 then
  3041. begin
  3042. Result := FList^[FCount - 1];
  3043. Delete(FCount - 1);
  3044. end
  3045. else
  3046. Result := 0;
  3047. end;
  3048. procedure TLongWordList.AddLongWords(const First: PLongWord; n: Integer);
  3049. begin
  3050. if n < 1 then
  3051. Exit;
  3052. AdjustCapacityToAtLeast(Count + n);
  3053. System.Move(First^, FList[FCount], n * SizeOf(LongWord));
  3054. FCount := FCount + n;
  3055. end;
  3056. procedure TLongWordList.AddLongWords(const aList: TLongWordList);
  3057. begin
  3058. if not Assigned(aList) then
  3059. Exit;
  3060. AddLongWords(@aList.List[0], aList.Count);
  3061. end;
  3062. procedure TLongWordList.AddLongWords(const anArray: array of LongWord);
  3063. var
  3064. n: Integer;
  3065. begin
  3066. n := Length(anArray);
  3067. if n > 0 then
  3068. AddLongWords(@anArray[0], n);
  3069. end;
  3070. function LongWordSearch(item: LongWord; list: PLongWordVector; Count: Integer): Integer; register;
  3071. var i : integer;
  3072. begin
  3073. result:=-1;
  3074. for i := 0 to Count-1 do begin
  3075. if list^[i]=item then begin
  3076. result:=i;
  3077. break;
  3078. end;
  3079. end;
  3080. end;
  3081. function TLongWordList.IndexOf(item: Integer): LongWord; register;
  3082. begin
  3083. Result := LongWordSearch(item, FList, FCount);
  3084. end;
  3085. // ------------------------------------------------------------------
  3086. initialization
  3087. // ------------------------------------------------------------------
  3088. RegisterClasses([TAffineVectorList, TVectorList, TTexPointList, TSingleList,
  3089. TDoubleList, T4ByteList, TLongWordList]);
  3090. end.