problem with Maps and Vectors

Monkey Forums/Monkey Programming/problem with Maps and Vectors

AdamRedwoods(Posted 2012) [#1]
Hi

I'm having an odd problem with Map<Vector, Vector> and was wondering if someone could point out what I'm doing wrong.

I've isolated my code to:


I get a NULL ERROR for the Print vx.x in the Sort method. (for all targets)

I may be missing something obvious, or setting up my Map incorrectly.
THANKS!


Xaron(Posted 2012) [#2]
I think the error is that you just don't create a new Map within your constructor (which is missing) in your NormMap class.

So you have an access to a (base class) map which doesn't exist. Just a wild guess at my first look!


muddy_shoes(Posted 2012) [#3]
This is a documentation fail. The Monkey implementation of Map requires that the keys can be ordered uniquely and this requirement lands on the Compare function. Your compare method:

Method Compare:Int( l:Vector,r:Vector )
    If l.x = r.x And l.y = r.y And l.z = r.z Then Return 0
    Return -1
End


This doesn't meet the requirement as all it does is define a Vector as equal to or not equal to the one being compared. You don't have a concept of greater than or less than, just "-1 means different". What this means is that when the vectors are added, it's not possible to build the Red-Black tree that underlies the map as the ordering relationships are invalid. An obvious example is that two Vectors that are not equal are both greater than and less than each other by your comparison depending on which you happen to put first in the parameters.

The fix is to create a Compare method that actually orders your keys. This is a bit tricky with a 3D vector as the ordering is 1D. To do it you need to have known bounds so that you can construct a proxy ordering value. For example:

    
Method Compare:Int( l:Vector,r:Vector )
    Return 10000*(l.x-r.x) + 100*(l.y-r.y) + (l.z-r.z)
End


That works for your test case, but you'd need to think more about your actual usage to come up with something that works for you.


marksibly(Posted 2012) [#4]
Hi,

Here's another approach that can easily be modified to work with all sorts of data types:

Method Compare:Int( lhs:Vector,rhs:Vector )
	If lhs.x<rhs.x Return -1
	If lhs.x>rhs.x Return 1
	If lhs.y<rhs.y Return -1
	If lhs.y>rhs.y Return 1
	If lhs.z<rhs.z Return -1
	Return lhs.z>rhs.z
End


This is similar to doing a memcmp() in C.


muddy_shoes(Posted 2012) [#5]
If you do that you'd still be advised to think about the ordering of your tests based on the actual usage of your Vector types. For instance, if you're doing some sort of pseudo-3D vertical-scroller, the X and Z components are going to be a lot less likely to differentiate than the Y.


AdamRedwoods(Posted 2012) [#6]
Aha! yes, I was trying to do a simple compare because I didn't need them ordered, but now I see that the compare return values are important for Get() values as well.

I see now, thank you!