struct LocalityEntryAxis ( Negative = #(), Positive = #(), fn Dispose = ( for Direction in #( this.Negative, this.Positive ) do ( for Element in Direction do ( if( ClassOf Element == LocalityEntryAxis ) then ( Element.Dispose() ) ) Free Direction ) ), fn GetAllEntries = ( MasterEntryList = #() for Direction in #( this.Negative, this.Positive ) do ( for Element in Direction do ( if( Element != Undefined )then ( if( ClassOf Element == LocalityEntryAxis ) then ( CurrentEntryList = Element.GetAllEntries() Join MasterEntryList CurrentEntryList ) else ( Join MasterEntryList Element ) ) ) ) return MasterEntryList ) ) --Stores any form of data using positions as locality keys. This is useful for matching points from one mesh too many meshes. --http://en.wikipedia.org/wiki/Locality-sensitive_hashing struct LocalityData ( --Bucket size in metres (greatly effects memory and speed) BucketSize = 3.5, OffsetPositionList = #([0,0,0]), --Base entry axis XEntryAxis = LocalityEntryAxis(), /*------------------------------------------------------------------------------ Gets the key for the passed value based off the current BucketSize */------------------------------------------------------------------------------ fn GetEntryKey InputValue = ( ReturnValue = ( Ceil ( Abs ( InputValue ) / BucketSize ) ) as Integer if( ReturnValue != 0 ) then ( return ReturnValue ) else ( return 1 ) ), /*------------------------------------------------------------------------------ Adds the passed InputValue into this locality data set using InputPosition as the key */------------------------------------------------------------------------------ fn AddEntry InputPosition InputValue = ( --Get X axis direction XEntryAxisDirection if( InputPosition.X > 0 ) then ( XEntryAxisDirection = XEntryAxis.Positive ) else ( XEntryAxisDirection = XEntryAxis.Negative ) --Get Y axis XKey = this.GetEntryKey InputPosition.X YEntryAxis = XEntryAxisDirection[XKey] if( YEntryAxis == Undefined) then ( YEntryAxis = LocalityEntryAxis() XEntryAxisDirection[XKey] = YEntryAxis ) --Get Y axis direction YEntryAxisDirection if( InputPosition.Y > 0 ) then ( YEntryAxisDirection = YEntryAxis.Positive ) else ( YEntryAxisDirection = YEntryAxis.Negative ) --Get Z axis YKey = this.GetEntryKey InputPosition.Y ZEntryAxis = YEntryAxisDirection[YKey] if( ZEntryAxis == Undefined) then ( ZEntryAxis = LocalityEntryAxis() YEntryAxisDirection[YKey] = ZEntryAxis ) --Get Z axis direction ZEntryAxisDirection if( InputPosition.Z > 0 ) then ( ZEntryAxisDirection = ZEntryAxis.Positive ) else ( ZEntryAxisDirection = ZEntryAxis.Negative ) --Set Value --------------------------- ZKey = this.GetEntryKey InputPosition.Z if( ZEntryAxisDirection[ZKey] == Undefined ) then ( ZEntryAxisDirection[ZKey] = #( DataPair Position:InputPosition Value:InputValue ) ) else ( Append ZEntryAxisDirection[ZKey] ( DataPair Position:InputPosition Value:InputValue ) ) ), /*------------------------------------------------------------------------------ Gets the value for the closest entry based of the passed InputPosition */------------------------------------------------------------------------------ fn GetBucketEntries InputPosition = ( --Get X axis direction XEntryAxisDirection if( InputPosition.X > 0 ) then ( XEntryAxisDirection = XEntryAxis.Positive ) else ( XEntryAxisDirection = XEntryAxis.Negative ) --Get Y axis XKey = this.GetEntryKey InputPosition.X YEntryAxis = XEntryAxisDirection[XKey] if( YEntryAxis == Undefined) then ( return Undefined ) --Get Y axis direction YEntryAxisDirection if( InputPosition.Y > 0 ) then ( YEntryAxisDirection = YEntryAxis.Positive ) else ( YEntryAxisDirection = YEntryAxis.Negative ) --Get Z axis YKey = this.GetEntryKey InputPosition.Y ZEntryAxis = YEntryAxisDirection[YKey] if( ZEntryAxis == Undefined) then ( return Undefined ) --Get Z axis direction ZEntryAxisDirection if( InputPosition.Z > 0 ) then ( ZEntryAxisDirection = ZEntryAxis.Positive ) else ( ZEntryAxisDirection = ZEntryAxis.Negative ) --Get Value --------------------------- ZKey = this.GetEntryKey InputPosition.Z if( ZEntryAxisDirection[ZKey] == Undefined ) then ( return Undefined ) else ( return ZEntryAxisDirection[ZKey] ) ), /*------------------------------------------------------------------------------ Gets closest entry to the passed position */------------------------------------------------------------------------------ fn GetClosestEntry InputPosition = ( EntryList = this.GetEntries InputPosition ClosestEntry = Undefined for Entry in EntryList do ( if( ClosestEntry == Undefined ) then ( EntryDistance = Distance Entry.Position InputPosition ClosestEntry = DataPair Entry:Entry Distance:EntryDistance ) else ( EntryDistance = Distance Entry.Position InputPosition if( EntryDistance < ClosestEntry.Distance ) then ( ClosestEntry = DataPair Entry:Entry Distance:EntryDistance ) ) ) if( ClosestEntry != Undefined ) then ( return ClosestEntry.Entry ) else ( return Undefined ) ), /*------------------------------------------------------------------------------ Returns all the entries for the passed positions. Will also check surrounding buckets */------------------------------------------------------------------------------ fn GetEntries InputPosition = ( EntryList = #() for OffsetPosition in OffsetPositionList do ( CurrentEntryList = this.GetBucketEntries( InputPosition + OffsetPosition ) if( CurrentEntryList != Undefined ) then ( Join EntryList CurrentEntryList ) ) return EntryList ), fn GetAllEntries = ( EntryList = XEntryAxis.GetAllEntries() ), /*------------------------------------------------------------------------------ Disposes of all resources related to this instances */------------------------------------------------------------------------------ fn Dispose = ( XEntryAxis.Dispose() --GC try ( GC() ) catch () try ( GC() ) catch () try ( GC() ) catch () try ( GC() ) catch () try ( GC() ) catch () ), fn SetBucketSearchBreadth InputBucketBreadth = ( OffsetList = #() for i = 0 to InputBucketBreadth do ( AppendIfUnique OffsetList ( this.BucketSize * i ) AppendIfUnique OffsetList ( this.BucketSize * -i ) ) this.OffsetPositionList = #() for OffsetX in OffsetList do ( for OffsetY in OffsetList do ( for OffsetZ in OffsetList do ( Append this.OffsetPositionList ( [ OffsetX, OffsetY, OffsetZ ] ) ) ) ) ) )