tbrosman/hxmath

Vector2 missing cross ?

Closed this issue · 4 comments

Was looking at porting some js code and noticed it defined a cross function so really I need something added along the lines of...

   @:op(A % B)
    public static inline function cross( u: Vertex, v: Vertex ) {
      return a.x * b.y - a.x * b.y;
    }

should I add pull request for Vector2, to include this?

Also I was thinking it would be nice to change Vector2 so that it is based off generic Pair class, which I would also use for an Edge class.

I was looking at something like...

typedef Edge = Pair<Int>;
class Pair<T> {
    public var x: T;
    public var y: T;
    public function new( x_: T, y_: T ){
        x = x_;
        y = y_;
    }
    @:keep
    public function toString() {
        return '($x, $y)';
    }
}

#if HXMATH_USE_OPENFL_STRUCTURES
typedef Vertex = flash.geom.Point;
#else
typedef Vertex = Pair<Float>;
#end

@:forward(x, y)
abstract Vector2(Vertex) from Vertex to Vertex
{

I probably need a Node class as well but not sure that really fits with your project but incase you have something similar that I should look at?

class Node<T> {
    public var prev: Node<T>;
    public var next: Node<T>;
    public var value: T = Null<T>;
    public function new( value_: T ){
        value = value_;
    }
    @:keep
    public function toString() {
        return value; //?
    }
    public function toStringOrder() {
        return '' + Std.string( prev.value ) + '->' + Std.string( value ) + '->' + Std.string( next.value );
    }
}

Cross products and 2D spaces

The operation you're describing is actually a determinant of two 2D vectors. This is a bit different from cross products.

Non-trivial cross products exist (in the mathematical sense) for R^3 and R^7 spaces. The signature of this operation is Vector X Vector -> Vector. A determinant of two R^2 vectors has the signature Vector X Vector -> Scalar. It also has some interesting properties of its own, namely that you can get information about orientations/angles.

  1. Say you have some normalized vector V = [x, y] and a rotated V' = R(angle) * V.
  2. Expanding using your standard 2D rotation matrix, V' = [cos(angle)*x - sin(angle)*y, sin(angle)*x + cos(angle)*y].
  3. The determinant |V V'| = x * (sin(angle)*x + cos(angle)*y) - y * (cos(angle)*x - sin(angle)*y).
  4. Grouping like sin/cos together: (x^2)sin(angle) + (xy)cos(angle) - (xy)cos(angle) + (y^2)sin(angle) = (x^2)sin(angle) + (y^2)sin(angle) = (x^2 + y^2)sin(angle) = [by the fact |V| == 1] sin(angle).
  5. Therefore, the determinant can give you the sin of the angle between two normalized vectors.

Similar functionality is already exposed in hxmath.

  • MathUtil.det2x2 gives you the determinant (though you have to specify components, not vectors)
  • MathUtil.orient2d is the orientation predicate which is based on the properties of the determinant
  • Vector2.signedAngleWith uses the determinant to find the sign of the angle between two vectors

Are there any use cases you can think of that aren't covered by these operations?

Pair

For the general case (e.g. Pair), this one is out of scope because it would be impossible to guarantee correct implementations of all the mathematical operations for different scalar types. For the specific case of Pair it is too specific a request/requirement to go into the main hxmath library. It would be nice if abstracts allowed you to change the underlying type without modifying the library they exist in. Typedefs allow you to kind of do this but aren't performant on native targets (or weren't last time I checked).

Node

I'm assuming you're looking for some kind of doubly-linked list implementation? Long ago I was using polygonal-ds for a lot of this stuff, but later on just ended up implementing my own datastructures for graphs/etc. This was 2-3 years ago and I'm certain there is a better option now. I haven't found it yet though.

Think my original question related to Triangulations port, since found the triangulation iterative ruppert approach is quite slow so rather academic project in terms of real time use at moment at least. I am unsure if the related code is in khamath currently ( which I have added some features from the original kha.math ) or the project itself, but I did write my own dynamic link list in the project dllnode. I did not end up using hxmath.

Ah, interesting. I had since lost the original context for this issue (hence my pruning).

FYI, polygonal-ds has a dynamic linked list implementation. Sadly, that library is kind of gigantic/bloated (or at least it was years ago).

I do use polygonal from time to time but getting his dll to work with triangulations seemed lot of effort and also overkill for my needs. The one I created is very simple.
https://github.com/nanjizal/triangulations/blob/master/triangulations/DllNode.hx
I have a feeling for the cross thing I moved to naming it perp instead, khamath normally seems to do most of what I need most of it's borrowed from Kha with Roberts permission I should really pull request some of my improvements to the Kha one, but I am not sure my improvements are all good they are just result of use with various projects and ports.
https://github.com/nanjizal/khaMath/blob/master/khaMath/Vector2.hx#L46