Fork me on GitHub
#datavis
<
2016-01-01
>
meow19:01:44

@mikera: What do I need to do to get a Vec3 vector from core.matrix with (set-current-implementation :vectorz)? Or does this do the trick:

(array [1 2 3])
=> #vectorz/vector[1.0 2.0 3.0]

meow19:01:33

The current string versions of vectors and matrices doesn't match the documentation so it gets a little confusing.

mikera19:01:40

That's actually a dense array backed Vector. If you want the primitive Vector3 you can use mikera.vectorz.core/vec3

mikera19:01:07

Or you van just use Java interop to instantiate a Vector3 directly... that will actually be faster as it avoids some Clojure overhead

meow20:01:19

This is to store a whole bunch of vertices, so faster is better.

meow20:01:52

So what would that Java interop look like?

meow20:01:18

I guess I need to import something from vectorz?

meow20:01:52

I have to say as someone new to matrices that my impression so far of core.matrix is that the code looks really good - well organized namespaces, docstrings on everything, readable code, etc. Very nice.

meow20:01:01

The documentation, on the other hand, is not up-to-par. It has taken me far too long to understand the relationship between all the pieces and I don't know how to do something basic, like create a Vector3, and there is nothing to walk me from a beginner level to an intermediate level. And I think I'm reasonably intelligent and have been coding for some time now, so I don't think it's just me. And if what I say is true then you are probably losing a lot of people who might otherwise give core.matrix a shot.

meow20:01:56

Take that as tough love from someone who does actually care about your project and wants it to succeed.

meow20:01:02

So are these examples on the wiki no longer valid? https://github.com/mikera/vectorz-clj/wiki/Examples

mikera20:01:32

Hmmm example should still be valid but the underlying types might have changed, as has the string representation

meow20:01:52

That very first example contradicts what you just told me:

(def v (array [1 2 3]))
; => #<Vector3 [1.0,2.0,3.0]>

meow20:01:44

No offense, but, frustrating as fsck, if you don't mind me saying so. 😱

mikera20:01:48

Yeah, you now get a Vector with length 3

mikera20:01:51

I'll have a check through the docs and see what is useful to update. Contributions also welcome, if you find anything that can be improved.

meow20:01:21

Using nREPL in Cursive this is what I see:

(def v (array [1 2 3]))
=> #'cad.mesh.core/v
v
=> #vectorz/vector[1.0 2.0 3.0]

meow20:01:16

First I have to understand how to make any improvements before I can contribute. And I'd be happy to contribute, unless I give up.

mikera20:01:22

Yeah the string representation changed to support tagged reader literals

mikera20:01:59

It should still behave the same however, it is still a mutable length 3 vector

meow20:01:35

But is it the magical Vector3 that is listed as a feature and that you just told me I should use Java interop to create?

meow20:01:16

The old string rep looked that way.

meow20:01:26

This is me taking my very first step to make use of a Vector3 in my mesh processing code. That's all I'm trying to do at this point.

meow20:01:59

I've got:

(:require [clojure.core.matrix :refer :all]
            [clojure.core.matrix.operators :refer :all]
and (set-current-implementation :vectorz) and I can follow the examples in the REPL. That's where I'm at.

meow20:01:41

And I'm looking at examples the have use which I never use because I thought it was not considered good practice any more and the examples don't match what I'm seeing in the REPL and they don't match in a way that is hard to ignore because I can't tell what type I'm dealing with and that's kind of the point of using core.matrix and optimizing my code. 😞

mikera20:01:25

(class (array :vectorz [1 2 3])) => mikera.vectorz.Vector

mikera20:01:51

(class (Vector3/of 1 2 3)) => mikera.vectorz.Vector3

mikera20:01:44

(class (mikera.vectorz.core/vec3 1 2 3)) => mikera.vectorz.Vector3

mikera20:01:53

It sounds like you want one of the latter two options

meow20:01:35

Okay, how are you getting a Vector3? It isn't available in my current setup. I need another :require

mikera20:01:09

It's a Java import, add following to your ns

mikera20:01:11

(:import [mikera.vectorz Vector1 Vector2 Vector3 Vector4])

meow20:01:07

Sweet. TYVM

(class (Vector3/of 1 2 3))
=> mikera.vectorz.Vector3

meow20:01:25

This is to store the [x y z] vertices so that should work.

meow20:01:14

Making this change is going to break Humpty Dumpty into a bunch of pieces that I'll need to put back together. Wish me luck. 😉

mikera20:01:23

Good luck! Excited to see the results!

meow21:01:32

@mikera: I will definitely let you know. Working on it now.

meow21:01:27

So it looks like all the namespaces where I'm doing matrix manipulations will need to have this added to them:

(:refer-clojure :exclude [+ - * / == min max])
  (:require [clojure.core.matrix.operators :refer :all]

meow21:01:58

@mikera: Question for you. I need an interpolate function and seem to recall that vectorz had one but it isn't in the core.matrix api. Is that correct?

mikera21:01:08

You can use scale-add! for interpolation in the core.matrix API, it's a relatively new function

meow21:01:48

normalise instead of normalize? Got something against American English?

meow22:01:35

@mikera: I don't think core.matrix is the place to fight a language battle - I suggest giving in and using normalize.

meow22:01:02

and whatever other variations are lurking in there

meow22:01:46

All unnecessary and easily avoidable barriers to adoption should be removed.

mikera22:01:09

core.matrix uses international / british english as standard. Not going to change simple_smile

meow22:01:49

@mikera: I'm calculating the area of triangles and the old code used a magnitude of a vector with code like this: (vm/rewrite-v3 buf (Math/sqrt (mm/madd x x y y z z))))

meow22:01:31

Is there a simple equivalent in core.matrix - with or without british spelling... 😉

meow22:01:37

This is the untested code I've got so far for this:

(defn mag [[x y z]]
  (Math/sqrt (+ x x y y z z)))

(defn norm-sign3
  [a b c] (mag (cross (- b a) (- c a))))

(defn tri-area3
  [a b c] (* 0.5 (norm-sign3 a b c)))

mikera22:01:38

You can use length to get the Euclidean length and cross for the cross product

meow22:01:38

And this pulls it all together:

(defn area
  [face]
  ((if (= 3 (count face))
     (apply tri-area3 face)
     (let [cent (centroid face)]
       (reduce + (map (fn [[v1 v2]] (tri-area3 cent v1 v2))
                      (vert-pairs face)))))))

meow22:01:28

I still need to brush up on my maths. Been a long time.

mikera22:01:58

You can avoid using the centroid too I think, just use one of the points

meow22:01:12

See how I said "maths" instead of "math" - so British of me. 😉

mikera22:01:25

Though you need to be careful about signs if the face is non-convex....

meow22:01:33

Well, the face might not be planar, so area is not going to be %100 relevant or accurate, but I don't care so I figured triangulating it with the centroid would be reasonable.

mikera22:01:42

Ah that makes sense

meow22:01:29

Yeah, I'm just using it as a characteristic for some of the face coloring algorithms.

meow22:01:12

And, actually, at the point I apply it they are all triangles, but I generalize the code regardless.

meow22:01:54

Hopefully the code I have will work and then we can clean it up later.

meow22:01:07

The old code worked...

meow22:01:47

I'm just trying to do the least possible to convert to core.matrix and then let you review it.

meow23:01:37

My brain is about fried. Not sure if I can convert this to core.matrix:

(defn centroid
  [[x & xs :as coll]]
  (case (count coll)
    0 nil
    1 x
    2 (gc/mix x (first xs))
    (let [s (/ 1.0 (count coll))
          f (fn [x _] (* x s))]
      (gc/reduce-vector x + f xs))))