{"action":"created","comment":{"url":"https://api.github.com/repos/softdevteam/lspace/pulls/comments/40822205","id":40822205,"diff_hunk":"@@ -0,0 +1,443 @@\n+use std::ops::{Mul};\n+\n+use geom::vector2::Vector2;\n+use geom::point2::Point2;\n+\n+#[derive(Debug, Copy, Clone, PartialEq)]\n+pub struct AffineXform2 {\n+    pub v: [[f64; 3]; 2],\n+}\n+\n+impl AffineXform2 {\n+    pub fn new(a: f64, b: f64, x: f64, c: f64, d: f64, y: f64) -> AffineXform2 {\n+        return AffineXform2{v: [[a, b, x], [c, d, y]]};\n+    }\n+\n+    pub fn identity() -> AffineXform2 {\n+        return AffineXform2{v: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]};\n+    }\n+\n+    pub fn translate(t: Vector2) -> AffineXform2 {\n+        return AffineXform2{v: [[1.0, 0.0, t.x], [0.0, 1.0, t.y]]};\n+    }\n+\n+    pub fn uniform_scale(s: f64) -> AffineXform2 {\n+        return AffineXform2{v: [[s, 0.0, 0.0], [0.0, s, 0.0]]};\n+    }\n+\n+    pub fn scale(s: Vector2) -> AffineXform2 {\n+        return AffineXform2{v: [[s.x, 0.0, 0.0], [0.0, s.y, 0.0]]};\n+    }\n+\n+    pub fn rotate(theta_radians: f64) -> AffineXform2 {\n+        let s = theta_radians.sin();\n+        let c = theta_radians.cos();\n+        return AffineXform2{v: [[c, -s, 0.0], [s, c, 0.0]]};\n+    }\n+\n+\n+    pub fn determinant(&self) -> f64 {\n+        return self.v[0][0] * self.v[1][1] - self.v[0][1] * self.v[1][0];\n+    }\n+\n+    pub fn inverse(&self) -> AffineXform2 {\n+        // Compute reciprocal of determinant\n+        let rd = 1.0 / self.determinant();\n+        // Compute inverse of 2x2 sub-matrix\n+        let a = self.v[1][1] * rd;\n+        let b = self.v[0][1] * -rd;\n+        let c = self.v[1][0] * -rd;\n+        let d = self.v[0][0] * rd;\n+        // Compute translation part\n+        let x = -self.v[0][2] * a - self.v[1][2] * b;\n+        let y = -self.v[0][2] * c - self.v[1][2] * d;\n+        return AffineXform2{v: [[a, b, x], [c, d, y]]};\n+    }\n+}\n+\n+// MULTIPLY BY Vector2; apply scale but not translation\n+\n+impl Mul<Vector2> for AffineXform2 {\n+    type Output = Vector2;\n+\n+    fn mul(self, v: Vector2) -> Vector2 {\n+        return Vector2::new(v.x * self.v[0][0] + v.y * self.v[0][1],\n+                            v.x * self.v[1][0] + v.y * self.v[1][1]);\n+    }\n+}\n+\n+impl <'a> Mul<Vector2> for &'a AffineXform2 {\n+    type Output = Vector2;\n+\n+    fn mul(self, v: Vector2) -> Vector2 {\n+        return Vector2::new(v.x * self.v[0][0] + v.y * self.v[0][1],\n+                            v.x * self.v[1][0] + v.y * self.v[1][1]);\n+    }\n+}\n+\n+impl <'a> Mul<&'a Vector2> for AffineXform2 {\n+    type Output = Vector2;\n+\n+    fn mul(self, v: &'a Vector2) -> Vector2 {\n+        return Vector2::new(v.x * self.v[0][0] + v.y * self.v[0][1],\n+                            v.x * self.v[1][0] + v.y * self.v[1][1]);\n+    }\n+}\n+\n+impl <'a, 'b> Mul<&'b Vector2> for &'a AffineXform2 {\n+    type Output = Vector2;\n+\n+    fn mul(self, v: &'b Vector2) -> Vector2 {\n+        return Vector2::new(v.x * self.v[0][0] + v.y * self.v[0][1],\n+                            v.x * self.v[1][0] + v.y * self.v[1][1]);\n+    }\n+}\n+\n+// MULTIPLY BY Point2; apply scale and translation\n+\n+impl Mul<Point2> for AffineXform2 {\n+    type Output = Point2;\n+\n+    fn mul(self, p: Point2) -> Point2 {\n+        return Point2::new(p.x * self.v[0][0] + p.y * self.v[0][1] + self.v[0][2],\n+                           p.x * self.v[1][0] + p.y * self.v[1][1] + self.v[1][2]);\n+    }\n+}\n+\n+impl <'a> Mul<Point2> for &'a AffineXform2 {\n+    type Output = Point2;\n+\n+    fn mul(self, p: Point2) -> Point2 {\n+        return Point2::new(p.x * self.v[0][0] + p.y * self.v[0][1] + self.v[0][2],\n+                           p.x * self.v[1][0] + p.y * self.v[1][1] + self.v[1][2]);\n+    }\n+}\n+\n+impl <'a> Mul<&'a Point2> for AffineXform2 {\n+    type Output = Point2;\n+\n+    fn mul(self, p: &'a Point2) -> Point2 {\n+        return Point2::new(p.x * self.v[0][0] + p.y * self.v[0][1] + self.v[0][2],\n+                           p.x * self.v[1][0] + p.y * self.v[1][1] + self.v[1][2]);\n+    }\n+}\n+\n+impl <'a, 'b> Mul<&'b Point2> for &'a AffineXform2 {\n+    type Output = Point2;\n+\n+    fn mul(self, p: &'b Point2) -> Point2 {\n+        return Point2::new(p.x * self.v[0][0] + p.y * self.v[0][1] + self.v[0][2],\n+                           p.x * self.v[1][0] + p.y * self.v[1][1] + self.v[1][2]);\n+    }\n+}\n+\n+// MULTIPLY BY AffineXform2; matrix multiplication\n+\n+impl Mul<AffineXform2> for AffineXform2 {\n+    type Output = AffineXform2;\n+\n+    fn mul(self, x: AffineXform2) -> AffineXform2 {\n+        return AffineXform2{v: [\n+                [\n+                    self.v[0][0] * x.v[0][0] + self.v[0][1] * x.v[1][0],\n+                    self.v[0][0] * x.v[0][1] + self.v[0][1] * x.v[1][1],\n+                    self.v[0][0] * x.v[0][2] + self.v[0][1] * x.v[1][2] + self.v[0][2],\n+                ],\n+                [\n+                    self.v[1][0] * x.v[0][0] + self.v[1][1] * x.v[1][0],\n+                    self.v[1][0] * x.v[0][1] + self.v[1][1] * x.v[1][1],\n+                    self.v[1][0] * x.v[0][2] + self.v[1][1] * x.v[1][2] + self.v[1][2],\n+                ],\n+            ]};\n+    }\n+}\n+\n+impl <'a> Mul<AffineXform2> for &'a AffineXform2 {\n+    type Output = AffineXform2;\n+\n+    fn mul(self, x: AffineXform2) -> AffineXform2 {\n+        return AffineXform2{v: [\n+                [\n+                    self.v[0][0] * x.v[0][0] + self.v[0][1] * x.v[1][0],\n+                    self.v[0][0] * x.v[0][1] + self.v[0][1] * x.v[1][1],\n+                    self.v[0][0] * x.v[0][2] + self.v[0][1] * x.v[1][2] + self.v[0][2],\n+                ],\n+                [\n+                    self.v[1][0] * x.v[0][0] + self.v[1][1] * x.v[1][0],\n+                    self.v[1][0] * x.v[0][1] + self.v[1][1] * x.v[1][1],\n+                    self.v[1][0] * x.v[0][2] + self.v[1][1] * x.v[1][2] + self.v[1][2],\n+                ],\n+            ]};\n+    }\n+}\n+\n+impl <'a> Mul<&'a AffineXform2> for AffineXform2 {\n+    type Output = AffineXform2;\n+\n+    fn mul(self, x: &'a AffineXform2) -> AffineXform2 {\n+        return AffineXform2{v: [\n+                [\n+                    self.v[0][0] * x.v[0][0] + self.v[0][1] * x.v[1][0],\n+                    self.v[0][0] * x.v[0][1] + self.v[0][1] * x.v[1][1],\n+                    self.v[0][0] * x.v[0][2] + self.v[0][1] * x.v[1][2] + self.v[0][2],\n+                ],\n+                [\n+                    self.v[1][0] * x.v[0][0] + self.v[1][1] * x.v[1][0],\n+                    self.v[1][0] * x.v[0][1] + self.v[1][1] * x.v[1][1],\n+                    self.v[1][0] * x.v[0][2] + self.v[1][1] * x.v[1][2] + self.v[1][2],\n+                ],\n+            ]};\n+    }\n+}\n+\n+impl <'a, 'b> Mul<&'b AffineXform2> for &'a AffineXform2 {\n+    type Output = AffineXform2;\n+\n+    fn mul(self, x: &'b AffineXform2) -> AffineXform2 {\n+        return AffineXform2{v: [\n+                [\n+                    self.v[0][0] * x.v[0][0] + self.v[0][1] * x.v[1][0],\n+                    self.v[0][0] * x.v[0][1] + self.v[0][1] * x.v[1][1],\n+                    self.v[0][0] * x.v[0][2] + self.v[0][1] * x.v[1][2] + self.v[0][2],\n+                ],\n+                [\n+                    self.v[1][0] * x.v[0][0] + self.v[1][1] * x.v[1][0],\n+                    self.v[1][0] * x.v[0][1] + self.v[1][1] * x.v[1][1],\n+                    self.v[1][0] * x.v[0][2] + self.v[1][1] * x.v[1][2] + self.v[1][2],\n+                ],\n+            ]};\n+    }\n+}\n+\n+\n+//\n+// TESTS\n+//\n+\n+#[cfg(test)]\n+mod tests {\n+    extern crate test;\n+\n+    use std::mem;\n+    use super::*;\n+    use geom::vector2::Vector2;\n+    use geom::point2::Point2;\n+\n+    const ALMOST_EQ_EPSILON: f64 = 1.0e-6;\n+\n+    macro_rules! assert_almost_eq {\n+        ($x:expr, $y:expr) => (\n+            if ($x).abs_sub($y) > ALMOST_EQ_EPSILON {\n+                panic!(\"assert_almost_eq failed: {} !=~ {}\", $x, $y);\n+            }\n+        );\n+    }\n+\n+    #[test]\n+    fn test_constructor() {\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[0][0], 1.0);\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[0][1], 2.0);\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[0][2], 3.0);\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[1][0], 4.0);\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[1][1], 5.0);\n+        assert_eq!(AffineXform2::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0).v[1][2], 6.0);\n+    }\n+\n+    #[test]\n+    fn test_identity() {\n+        let a = AffineXform2::identity();\n+        assert_eq!(a.v[0][0], 1.0);\n+        assert_eq!(a.v[0][1], 0.0);\n+        assert_eq!(a.v[0][2], 0.0);\n+        assert_eq!(a.v[1][0], 0.0);\n+        assert_eq!(a.v[1][1], 1.0);\n+        assert_eq!(a.v[1][2], 0.0);\n+    }\n+\n+    #[test]\n+    fn test_translate() {\n+        let a = AffineXform2::translate(Vector2::new(3.0, 4.0));\n+        assert_eq!(a.v[0][0], 1.0);\n+        assert_eq!(a.v[0][1], 0.0);\n+        assert_eq!(a.v[0][2], 3.0);\n+        assert_eq!(a.v[1][0], 0.0);\n+        assert_eq!(a.v[1][1], 1.0);\n+        assert_eq!(a.v[1][2], 4.0);\n+\n+        assert_eq!(a * Vector2::new(10.0, 20.0), Vector2::new(10.0, 20.0));\n+        assert_eq!(a * Point2::new(10.0, 20.0), Point2::new(13.0, 24.0));\n+    }\n+\n+    #[test]\n+    fn test_uniform_scale() {\n+        let a = AffineXform2::uniform_scale(2.0);\n+        assert_eq!(a.v[0][0], 2.0);\n+        assert_eq!(a.v[0][1], 0.0);\n+        assert_eq!(a.v[0][2], 0.0);\n+        assert_eq!(a.v[1][0], 0.0);\n+        assert_eq!(a.v[1][1], 2.0);\n+        assert_eq!(a.v[1][2], 0.0);\n+\n+        assert_eq!(a * Vector2::new(10.0, 20.0), Vector2::new(20.0, 40.0));\n+        assert_eq!(a * Point2::new(10.0, 20.0), Point2::new(20.0, 40.0));\n+    }\n+\n+    #[test]\n+    fn test_scale() {\n+        let a = AffineXform2::scale(Vector2::new(3.0, 4.0));\n+        assert_eq!(a.v[0][0], 3.0);\n+        assert_eq!(a.v[0][1], 0.0);\n+        assert_eq!(a.v[0][2], 0.0);\n+        assert_eq!(a.v[1][0], 0.0);\n+        assert_eq!(a.v[1][1], 4.0);\n+        assert_eq!(a.v[1][2], 0.0);\n+\n+        assert_eq!(a * Vector2::new(10.0, 20.0), Vector2::new(30.0, 80.0));\n+        assert_eq!(a * Point2::new(10.0, 20.0), Point2::new(30.0, 80.0));\n+    }\n+\n+    #[test]\n+    fn test_rotate() {\n+        let a = AffineXform2::rotate((90.0 as f64).to_radians());\n+        assert_almost_eq!(a.v[0][0], 0.0);\n+        assert_almost_eq!(a.v[0][1], -1.0);\n+        assert_almost_eq!(a.v[0][2], 0.0);\n+        assert_almost_eq!(a.v[1][0], 1.0);\n+        assert_almost_eq!(a.v[1][1], 0.0);\n+        assert_almost_eq!(a.v[1][2], 0.0);\n+\n+        assert_almost_eq!((a * Vector2::new(10.0, 20.0)).x, -20.0);\n+        assert_almost_eq!((a * Vector2::new(10.0, 20.0)).y, 10.0);\n+        assert_almost_eq!((a * Point2::new(10.0, 20.0)).x, -20.0);\n+        assert_almost_eq!((a * Point2::new(10.0, 20.0)).y, 10.0);\n+    }\n+\n+    #[test]\n+    fn test_inverse() {\n+        {\n+            let a = AffineXform2::identity();\n+            let b = a.inverse();\n+\n+            assert_almost_eq!(b.v[0][0], 1.0);\n+            assert_almost_eq!(b.v[0][1], 0.0);\n+            assert_almost_eq!(b.v[0][2], 0.0);\n+            assert_almost_eq!(b.v[1][0], 0.0);\n+            assert_almost_eq!(b.v[1][1], 1.0);\n+            assert_almost_eq!(b.v[1][2], 0.0);\n+        }\n+\n+        {\n+            let a = AffineXform2::translate(Vector2::new(2.0, 4.0));\n+            let b = a.inverse();\n+\n+            assert_almost_eq!(b.v[0][0], 1.0);\n+            assert_almost_eq!(b.v[0][1], 0.0);\n+            assert_almost_eq!(b.v[0][2], -2.0);\n+            assert_almost_eq!(b.v[1][0], 0.0);\n+            assert_almost_eq!(b.v[1][1], 1.0);\n+            assert_almost_eq!(b.v[1][2], -4.0);\n+        }\n+\n+        {\n+            let a = AffineXform2::uniform_scale(4.0);\n+            let b = a.inverse();\n+\n+            assert_almost_eq!(b.v[0][0], 0.25);\n+            assert_almost_eq!(b.v[0][1], 0.0);\n+            assert_almost_eq!(b.v[0][2], 0.0);\n+            assert_almost_eq!(b.v[1][0], 0.0);\n+            assert_almost_eq!(b.v[1][1], 0.25);\n+            assert_almost_eq!(b.v[1][2], 0.0);\n+        }\n+\n+        {\n+            let a = AffineXform2::scale(Vector2::new(2.0, 4.0));\n+            let b = a.inverse();\n+\n+            assert_almost_eq!(b.v[0][0], 0.5);\n+            assert_almost_eq!(b.v[0][1], 0.0);\n+            assert_almost_eq!(b.v[0][2], 0.0);\n+            assert_almost_eq!(b.v[1][0], 0.0);\n+            assert_almost_eq!(b.v[1][1], 0.25);\n+            assert_almost_eq!(b.v[1][2], 0.0);\n+        }\n+\n+        {\n+            let a = AffineXform2::rotate((90.0 as f64).to_radians());\n+            let b = a.inverse();\n+\n+            assert_almost_eq!(b.v[0][0], 0.0);\n+            assert_almost_eq!(b.v[0][1], 1.0);\n+            assert_almost_eq!(b.v[0][2], 0.0);\n+            assert_almost_eq!(b.v[1][0], -1.0);\n+            assert_almost_eq!(b.v[1][1], 0.0);\n+            assert_almost_eq!(b.v[1][2], 0.0);\n+        }\n+\n+        {\n+            let a = AffineXform2::new(2.0, 3.0, -7.0, 5.0, 11.0, 13.0);\n+            let ainv = a.inverse();\n+            let b = ainv * a;\n+\n+            let p0 = Point2::new(5.0, 3.0);\n+            let p1 = a * p0;\n+            let p2 = ainv * p1;\n+\n+            assert_almost_eq!(p0.x, p2.x);\n+            assert_almost_eq!(p0.y, p2.y);\n+\n+            assert_almost_eq!(b.v[0][0], 1.0);\n+            assert_almost_eq!(b.v[0][1], 0.0);\n+            assert_almost_eq!(b.v[0][2], 0.0);\n+            assert_almost_eq!(b.v[1][0], 0.0);\n+            assert_almost_eq!(b.v[1][1], 1.0);\n+            assert_almost_eq!(b.v[1][2], 0.0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_mul() {\n+        assert_eq!(AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * Vector2::new(2.0, 3.0),\n+                Vector2::new(13.0, 47.0));\n+        assert_eq!(&AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * Vector2::new(2.0, 3.0),\n+                Vector2::new(13.0, 47.0));\n+        assert_eq!(AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * &Vector2::new(2.0, 3.0),\n+                Vector2::new(13.0, 47.0));\n+        assert_eq!(&AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * &Vector2::new(2.0, 3.0),\n+                Vector2::new(13.0, 47.0));\n+\n+        assert_eq!(AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * Point2::new(2.0, 3.0),\n+                Point2::new(18.0, 60.0));\n+        assert_eq!(&AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * Point2::new(2.0, 3.0),\n+                Point2::new(18.0, 60.0));\n+        assert_eq!(AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * &Point2::new(2.0, 3.0),\n+                Point2::new(18.0, 60.0));\n+        assert_eq!(&AffineXform2::new(2.0, 3.0, 5.0, 7.0, 11.0, 13.0) * &Point2::new(2.0, 3.0),\n+                Point2::new(18.0, 60.0));\n+\n+        assert_eq!(AffineXform2::new(2.0, 3.0, 5.0,","path":"src/lib/lspace/geom/affinexform2.rs","position":418,"original_position":418,"commit_id":"f0313f7e13c29e5a416af171dd8e51158f7605d0","original_commit_id":"f0313f7e13c29e5a416af171dd8e51158f7605d0","user":{"login":"ltratt","id":20318,"avatar_url":"https://avatars.githubusercontent.com/u/20318?v=3","gravatar_id":"","url":"https://api.github.com/users/ltratt","html_url":"https://github.com/ltratt","followers_url":"https://api.github.com/users/ltratt/followers","following_url":"https://api.github.com/users/ltratt/following{/other_user}","gists_url":"https://api.github.com/users/ltratt/gists{/gist_id}","starred_url":"https://api.github.com/users/ltratt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ltratt/subscriptions","organizations_url":"https://api.github.com/users/ltratt/orgs","repos_url":"https://api.github.com/users/ltratt/repos","events_url":"https://api.github.com/users/ltratt/events{/privacy}","received_events_url":"https://api.github.com/users/ltratt/received_events","type":"User","site_admin":false},"body":"The formatting below this line seems a bit random? Can we tidy it up a bit?","created_at":"2015-09-30T17:15:35Z","updated_at":"2015-09-30T17:15:35Z","html_url":"https://github.com/softdevteam/lspace/pull/11#discussion_r40822205","pull_request_url":"https://api.github.com/repos/softdevteam/lspace/pulls/11","_links":{"self":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/comments/40822205"},"html":{"href":"https://github.com/softdevteam/lspace/pull/11#discussion_r40822205"},"pull_request":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/11"}}},"pull_request":{"url":"https://api.github.com/repos/softdevteam/lspace/pulls/11","id":46392393,"html_url":"https://github.com/softdevteam/lspace/pull/11","diff_url":"https://github.com/softdevteam/lspace/pull/11.diff","patch_url":"https://github.com/softdevteam/lspace/pull/11.patch","issue_url":"https://api.github.com/repos/softdevteam/lspace/issues/11","number":11,"state":"open","locked":false,"title":"Extensions to geometric primitives.","user":{"login":"Britefury","id":897534,"avatar_url":"https://avatars.githubusercontent.com/u/897534?v=3","gravatar_id":"","url":"https://api.github.com/users/Britefury","html_url":"https://github.com/Britefury","followers_url":"https://api.github.com/users/Britefury/followers","following_url":"https://api.github.com/users/Britefury/following{/other_user}","gists_url":"https://api.github.com/users/Britefury/gists{/gist_id}","starred_url":"https://api.github.com/users/Britefury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Britefury/subscriptions","organizations_url":"https://api.github.com/users/Britefury/orgs","repos_url":"https://api.github.com/users/Britefury/repos","events_url":"https://api.github.com/users/Britefury/events{/privacy}","received_events_url":"https://api.github.com/users/Britefury/received_events","type":"User","site_admin":false},"body":"This probably should have been in the previous PR. They would have been had I realised I would later implement them.\r\n\r\nReady for review and merge.\r\n\r\nImplemented `AffineXform2`; an affine transformation represented as a 2x3 matrix.\r\nAdded length and distance methods to `Vector2` and `Point2`.\r\nAdded `Vector2` <--> `Point2` conversion methods.\r\nAdded `centre`, `size` and `intersection` methods to `BBox2`.\r\nMoved `fast_min`, `fast_max`, `fast_minopt` and `fast_maxopt` functions out of `lreq` module into `fastminmax` module in `geom`.\r\n`lspace::graphics` package renamed to `lspace::geom`.\r\nRefactorings to other parts of LSpace to account for API changes.","created_at":"2015-09-30T11:57:38Z","updated_at":"2015-09-30T17:15:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"db0afc8d3acf6c37a67a50afa4a8d1140f1d57d9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/softdevteam/lspace/pulls/11/commits","review_comments_url":"https://api.github.com/repos/softdevteam/lspace/pulls/11/comments","review_comment_url":"https://api.github.com/repos/softdevteam/lspace/pulls/comments{/number}","comments_url":"https://api.github.com/repos/softdevteam/lspace/issues/11/comments","statuses_url":"https://api.github.com/repos/softdevteam/lspace/statuses/f0313f7e13c29e5a416af171dd8e51158f7605d0","head":{"label":"Britefury:geo-primitives-2","ref":"geo-primitives-2","sha":"f0313f7e13c29e5a416af171dd8e51158f7605d0","user":{"login":"Britefury","id":897534,"avatar_url":"https://avatars.githubusercontent.com/u/897534?v=3","gravatar_id":"","url":"https://api.github.com/users/Britefury","html_url":"https://github.com/Britefury","followers_url":"https://api.github.com/users/Britefury/followers","following_url":"https://api.github.com/users/Britefury/following{/other_user}","gists_url":"https://api.github.com/users/Britefury/gists{/gist_id}","starred_url":"https://api.github.com/users/Britefury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Britefury/subscriptions","organizations_url":"https://api.github.com/users/Britefury/orgs","repos_url":"https://api.github.com/users/Britefury/repos","events_url":"https://api.github.com/users/Britefury/events{/privacy}","received_events_url":"https://api.github.com/users/Britefury/received_events","type":"User","site_admin":false},"repo":{"id":41298538,"name":"lspace","full_name":"Britefury/lspace","owner":{"login":"Britefury","id":897534,"avatar_url":"https://avatars.githubusercontent.com/u/897534?v=3","gravatar_id":"","url":"https://api.github.com/users/Britefury","html_url":"https://github.com/Britefury","followers_url":"https://api.github.com/users/Britefury/followers","following_url":"https://api.github.com/users/Britefury/following{/other_user}","gists_url":"https://api.github.com/users/Britefury/gists{/gist_id}","starred_url":"https://api.github.com/users/Britefury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Britefury/subscriptions","organizations_url":"https://api.github.com/users/Britefury/orgs","repos_url":"https://api.github.com/users/Britefury/repos","events_url":"https://api.github.com/users/Britefury/events{/privacy}","received_events_url":"https://api.github.com/users/Britefury/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Britefury/lspace","description":"L-Space presentation system in Rust","fork":true,"url":"https://api.github.com/repos/Britefury/lspace","forks_url":"https://api.github.com/repos/Britefury/lspace/forks","keys_url":"https://api.github.com/repos/Britefury/lspace/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Britefury/lspace/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Britefury/lspace/teams","hooks_url":"https://api.github.com/repos/Britefury/lspace/hooks","issue_events_url":"https://api.github.com/repos/Britefury/lspace/issues/events{/number}","events_url":"https://api.github.com/repos/Britefury/lspace/events","assignees_url":"https://api.github.com/repos/Britefury/lspace/assignees{/user}","branches_url":"https://api.github.com/repos/Britefury/lspace/branches{/branch}","tags_url":"https://api.github.com/repos/Britefury/lspace/tags","blobs_url":"https://api.github.com/repos/Britefury/lspace/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Britefury/lspace/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Britefury/lspace/git/refs{/sha}","trees_url":"https://api.github.com/repos/Britefury/lspace/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Britefury/lspace/statuses/{sha}","languages_url":"https://api.github.com/repos/Britefury/lspace/languages","stargazers_url":"https://api.github.com/repos/Britefury/lspace/stargazers","contributors_url":"https://api.github.com/repos/Britefury/lspace/contributors","subscribers_url":"https://api.github.com/repos/Britefury/lspace/subscribers","subscription_url":"https://api.github.com/repos/Britefury/lspace/subscription","commits_url":"https://api.github.com/repos/Britefury/lspace/commits{/sha}","git_commits_url":"https://api.github.com/repos/Britefury/lspace/git/commits{/sha}","comments_url":"https://api.github.com/repos/Britefury/lspace/comments{/number}","issue_comment_url":"https://api.github.com/repos/Britefury/lspace/issues/comments{/number}","contents_url":"https://api.github.com/repos/Britefury/lspace/contents/{+path}","compare_url":"https://api.github.com/repos/Britefury/lspace/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Britefury/lspace/merges","archive_url":"https://api.github.com/repos/Britefury/lspace/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Britefury/lspace/downloads","issues_url":"https://api.github.com/repos/Britefury/lspace/issues{/number}","pulls_url":"https://api.github.com/repos/Britefury/lspace/pulls{/number}","milestones_url":"https://api.github.com/repos/Britefury/lspace/milestones{/number}","notifications_url":"https://api.github.com/repos/Britefury/lspace/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Britefury/lspace/labels{/name}","releases_url":"https://api.github.com/repos/Britefury/lspace/releases{/id}","created_at":"2015-08-24T11:06:39Z","updated_at":"2015-08-25T16:05:57Z","pushed_at":"2015-09-30T15:45:52Z","git_url":"git://github.com/Britefury/lspace.git","ssh_url":"git@github.com:Britefury/lspace.git","clone_url":"https://github.com/Britefury/lspace.git","svn_url":"https://github.com/Britefury/lspace","homepage":null,"size":328,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"softdevteam:master","ref":"master","sha":"76a0ae955f6936448e2a30c98e86f7a0c9fdfeb7","user":{"login":"softdevteam","id":10271085,"avatar_url":"https://avatars.githubusercontent.com/u/10271085?v=3","gravatar_id":"","url":"https://api.github.com/users/softdevteam","html_url":"https://github.com/softdevteam","followers_url":"https://api.github.com/users/softdevteam/followers","following_url":"https://api.github.com/users/softdevteam/following{/other_user}","gists_url":"https://api.github.com/users/softdevteam/gists{/gist_id}","starred_url":"https://api.github.com/users/softdevteam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/softdevteam/subscriptions","organizations_url":"https://api.github.com/users/softdevteam/orgs","repos_url":"https://api.github.com/users/softdevteam/repos","events_url":"https://api.github.com/users/softdevteam/events{/privacy}","received_events_url":"https://api.github.com/users/softdevteam/received_events","type":"Organization","site_admin":false},"repo":{"id":41298533,"name":"lspace","full_name":"softdevteam/lspace","owner":{"login":"softdevteam","id":10271085,"avatar_url":"https://avatars.githubusercontent.com/u/10271085?v=3","gravatar_id":"","url":"https://api.github.com/users/softdevteam","html_url":"https://github.com/softdevteam","followers_url":"https://api.github.com/users/softdevteam/followers","following_url":"https://api.github.com/users/softdevteam/following{/other_user}","gists_url":"https://api.github.com/users/softdevteam/gists{/gist_id}","starred_url":"https://api.github.com/users/softdevteam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/softdevteam/subscriptions","organizations_url":"https://api.github.com/users/softdevteam/orgs","repos_url":"https://api.github.com/users/softdevteam/repos","events_url":"https://api.github.com/users/softdevteam/events{/privacy}","received_events_url":"https://api.github.com/users/softdevteam/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/softdevteam/lspace","description":"L-Space presentation system in Rust","fork":false,"url":"https://api.github.com/repos/softdevteam/lspace","forks_url":"https://api.github.com/repos/softdevteam/lspace/forks","keys_url":"https://api.github.com/repos/softdevteam/lspace/keys{/key_id}","collaborators_url":"https://api.github.com/repos/softdevteam/lspace/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/softdevteam/lspace/teams","hooks_url":"https://api.github.com/repos/softdevteam/lspace/hooks","issue_events_url":"https://api.github.com/repos/softdevteam/lspace/issues/events{/number}","events_url":"https://api.github.com/repos/softdevteam/lspace/events","assignees_url":"https://api.github.com/repos/softdevteam/lspace/assignees{/user}","branches_url":"https://api.github.com/repos/softdevteam/lspace/branches{/branch}","tags_url":"https://api.github.com/repos/softdevteam/lspace/tags","blobs_url":"https://api.github.com/repos/softdevteam/lspace/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/softdevteam/lspace/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/softdevteam/lspace/git/refs{/sha}","trees_url":"https://api.github.com/repos/softdevteam/lspace/git/trees{/sha}","statuses_url":"https://api.github.com/repos/softdevteam/lspace/statuses/{sha}","languages_url":"https://api.github.com/repos/softdevteam/lspace/languages","stargazers_url":"https://api.github.com/repos/softdevteam/lspace/stargazers","contributors_url":"https://api.github.com/repos/softdevteam/lspace/contributors","subscribers_url":"https://api.github.com/repos/softdevteam/lspace/subscribers","subscription_url":"https://api.github.com/repos/softdevteam/lspace/subscription","commits_url":"https://api.github.com/repos/softdevteam/lspace/commits{/sha}","git_commits_url":"https://api.github.com/repos/softdevteam/lspace/git/commits{/sha}","comments_url":"https://api.github.com/repos/softdevteam/lspace/comments{/number}","issue_comment_url":"https://api.github.com/repos/softdevteam/lspace/issues/comments{/number}","contents_url":"https://api.github.com/repos/softdevteam/lspace/contents/{+path}","compare_url":"https://api.github.com/repos/softdevteam/lspace/compare/{base}...{head}","merges_url":"https://api.github.com/repos/softdevteam/lspace/merges","archive_url":"https://api.github.com/repos/softdevteam/lspace/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/softdevteam/lspace/downloads","issues_url":"https://api.github.com/repos/softdevteam/lspace/issues{/number}","pulls_url":"https://api.github.com/repos/softdevteam/lspace/pulls{/number}","milestones_url":"https://api.github.com/repos/softdevteam/lspace/milestones{/number}","notifications_url":"https://api.github.com/repos/softdevteam/lspace/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/softdevteam/lspace/labels{/name}","releases_url":"https://api.github.com/repos/softdevteam/lspace/releases{/id}","created_at":"2015-08-24T11:06:31Z","updated_at":"2015-08-25T16:04:12Z","pushed_at":"2015-09-30T11:57:39Z","git_url":"git://github.com/softdevteam/lspace.git","ssh_url":"git@github.com:softdevteam/lspace.git","clone_url":"https://github.com/softdevteam/lspace.git","svn_url":"https://github.com/softdevteam/lspace","homepage":null,"size":752,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/11"},"html":{"href":"https://github.com/softdevteam/lspace/pull/11"},"issue":{"href":"https://api.github.com/repos/softdevteam/lspace/issues/11"},"comments":{"href":"https://api.github.com/repos/softdevteam/lspace/issues/11/comments"},"review_comments":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/11/comments"},"review_comment":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/softdevteam/lspace/pulls/11/commits"},"statuses":{"href":"https://api.github.com/repos/softdevteam/lspace/statuses/f0313f7e13c29e5a416af171dd8e51158f7605d0"}}}}