Comments (12)
Hi @den1k - just checked in 2 pieces of functionality which now cause no more warnings when using the viz module with Reagent (still not tried with sablono or any other Om related libs).
Seqs of elements in SVG groups now have one level less of nesting and you'll need to insert a call to inject-element-attribs
(in the thi.ng.geom.svg.adapter
ns). This fn will generate unique IDs for each element in the SVG hiccup structure.
The below is a complete reagent component for reference:
(defn visualization
"Takes a geom.viz visualization spec map and generates a SVG component.
The call to inject-element-attribs ensures that all SVG elements have
an unique :key attribute, required for React.js."
[spec]
(->> spec
(viz/svg-plot2d-cartesian)
(svgadapt/inject-element-attribs svgadapt/key-attrib-injector)
(svg/svg {:width 600 :height 600})))
It'd be great if you could test this with any of the other libs.
Latest release version is: [thi.ng/geom "0.0.908"]
from geom.
I'm more of a reagent kinda person, so no 1st hand experience with sablono / om... But am really suprised that the bar graph fails of all the methods (which only uses rects & lines). Do you get an error or it just doesn't produce a DOM fragment? The svg-plot2d-cartesian
just produces hiccup vectors with nothing special. However for React components the issue is that attribs like :fill
, :stroke
etc. need to be nested under the :style
key in the :attribs
map. So instead of:
:attribs {:fill "none" :stroke "#0af"}
...you'll need to state these as:
:attribs {:style {:fill "none" :stroke "#0af"}}
(I don't know if that's the same in Om, but I guess so...)
For a non-React based example, check out the SVG physics demo here:
Source: https://github.com/thi-ng/demos/blob/master/geom/src/physics_demos/strands.cljs
Live: http://demo.thi.ng/geom/physics/strands.html
This demo uses the hiccup serializer in the domus lib
from geom.
The line-plot actually renders perfectly, apparently chrome also accepts tag attributes for properties like fill
. I got really excited when it worked. I thought: finally a D3 replacement where I could add event handlers in a data transformation step before passing it to sablono.
The bar graph breaks something in sablono's html
macro. The grid renders properly. Everything else ends up outside of the svg tag, rendered in span
s as react does with strings:
from geom.
I think this is really a shortcoming of sablono and other serializers. The bar graph hiccup looks like this below and serializes fine into an SVG DOM using my domus lib or in CLJ w/ hiccup:
[:g
nil
([:g
{:stroke "#ccc", :stroke-dasharray "1 1"}
(([:line {:x1 "50.00", :y1 "280.00", :x2 "50.00", :y2 "20.00"}]
[:line {:x1 "81.18", :y1 "280.00", :x2 "81.18", :y2 "20.00"}]
...)
([:line {:x1 "50.00", :y1 "267.00", :x2 "580.00", :y2 "267.00"}]
[:line {:x1 "50.00", :y1 "241.00", :x2 "580.00", :y2 "241.00"}]
...))]
([:g
{:stroke "#0af", :stroke-width "19px"}
(([:line {:x1 "81.18", :y1 "195.10", :x2 "81.18", :y2 "280.00"}]
...))])
[:g
{:stroke "black"}
(([:line {:x1 "50.00", :y1 "280.00", :x2 "50.00", :y2 "290.00"}]
...)
()
[:g
{:stroke "none",
:fill "black",
:font-family "Arial, sans-serif",
:font-size 10,
:text-anchor "middle"}
(([:text {:x "50.00", :y "300.00"} 1999]
...))]
[:line {:x1 "50.00", :y1 "280.00", :x2 "580.00", :y2 "280.00"}])]
[:g
{:stroke "black"}
(([:line {:x1 "50.00", :y1 "280.00", :x2 "40.00", :y2 "280.00"}]
...)
([:line {:x1 "50.00", :y1 "267.00", :x2 "45.00", :y2 "267.00"}]
...)
[:g
{:stroke "none",
:fill "black",
:font-family "Arial, sans-serif",
:font-size 10,
:text-anchor "end"}
(([:text {:x "35.00", :y "280.00"} "0.00"]
...))]
[:line {:x1 "50.00", :y1 "280.00", :x2 "50.00", :y2 "20.00"}])])]
I guess, it's the nested seqs which cause the serialization "hiccup" (pun intended! :) Will have to check if I can switch to mapcat
somewhere.
from geom.
thanks @postspectacular I'm a huge fan of the geom toolkit. Looking forward to use it more & more in the future!
from geom.
Thanks @postspectacular for adding keys! The bar chart now renders properly. I checked the line chart which has extra numbers in it's last svg group node.
It appears that the group should contain svg text nodes but instead it has plain numbers which react renders as spans.
This is the group:
[:g
{:stroke "none",
:fill "black",
:font-family "Arial, sans-serif",
:font-size 10,
:text-anchor "middle",
:key "G__2367"}
-1
-0.8
-0.6000000000000001
-0.4000000000000001
-0.20000000000000007
-5.551115123125783e-17
0.19999999999999996
0.39999999999999997
0.6
0.8
1]
Full output with injected keys:
[:g
{:key "G__2370"}
[:g
{:stroke "#caa", :stroke-dasharray "1 1", :key "G__2319"}
([:line
{:x1 "50.00",
:y1 "250.00",
:x2 "50.00",
:y2 "20.00",
:key "G__2285"}]
[:line
{:x1 "182.50",
:y1 "250.00",
:x2 "182.50",
:y2 "20.00",
:key "G__2286"}]
[:line
{:x1 "315.00",
:y1 "250.00",
:x2 "315.00",
:y2 "20.00",
:key "G__2287"}]
[:line
{:x1 "447.50",
:y1 "250.00",
:x2 "447.50",
:y2 "20.00",
:key "G__2288"}]
[:line
{:x1 "580.00",
:y1 "250.00",
:x2 "580.00",
:y2 "20.00",
:key "G__2289"}])
([:line
{:x1 "50.00",
:y1 "238.50",
:x2 "580.00",
:y2 "238.50",
:key "G__2290"}]
[:line
{:x1 "50.00",
:y1 "215.50",
:x2 "580.00",
:y2 "215.50",
:key "G__2291"}]
[:line
{:x1 "50.00",
:y1 "192.50",
:x2 "580.00",
:y2 "192.50",
:key "G__2292"}]
[:line
{:x1 "50.00",
:y1 "181.00",
:x2 "580.00",
:y2 "181.00",
:key "G__2293"}]
[:line
{:x1 "50.00",
:y1 "169.50",
:x2 "580.00",
:y2 "169.50",
:key "G__2294"}]
[:line
{:x1 "50.00",
:y1 "158.00",
:x2 "580.00",
:y2 "158.00",
:key "G__2295"}]
[:line
{:x1 "50.00",
:y1 "146.50",
:x2 "580.00",
:y2 "146.50",
:key "G__2296"}]
[:line
{:x1 "50.00",
:y1 "135.00",
:x2 "580.00",
:y2 "135.00",
:key "G__2297"}]
[:line
{:x1 "50.00",
:y1 "123.50",
:x2 "580.00",
:y2 "123.50",
:key "G__2298"}]
[:line
{:x1 "50.00",
:y1 "112.00",
:x2 "580.00",
:y2 "112.00",
:key "G__2299"}]
[:line
{:x1 "50.00",
:y1 "100.50",
:x2 "580.00",
:y2 "100.50",
:key "G__2300"}]
[:line
{:x1 "50.00",
:y1 "89.00",
:x2 "580.00",
:y2 "89.00",
:key "G__2301"}]
[:line
{:x1 "50.00",
:y1 "77.50",
:x2 "580.00",
:y2 "77.50",
:key "G__2302"}]
[:line
{:x1 "50.00",
:y1 "66.00",
:x2 "580.00",
:y2 "66.00",
:key "G__2303"}]
[:line
{:x1 "50.00",
:y1 "54.50",
:x2 "580.00",
:y2 "54.50",
:key "G__2304"}]
[:line
{:x1 "50.00",
:y1 "43.00",
:x2 "580.00",
:y2 "43.00",
:key "G__2305"}]
[:line
{:x1 "50.00",
:y1 "31.50",
:x2 "580.00",
:y2 "31.50",
:key "G__2306"}]
[:line
{:x1 "50.00",
:y1 "20.00",
:x2 "580.00",
:y2 "20.00",
:key "G__2307"}]
[:line
{:x1 "50.00",
:y1 "250.00",
:x2 "580.00",
:y2 "250.00",
:key "G__2308"}]
[:line
{:x1 "50.00",
:y1 "227.00",
:x2 "580.00",
:y2 "227.00",
:key "G__2309"}]
[:line
{:x1 "50.00",
:y1 "204.00",
:x2 "580.00",
:y2 "204.00",
:key "G__2310"}]
[:line
{:x1 "50.00",
:y1 "181.00",
:x2 "580.00",
:y2 "181.00",
:key "G__2311"}]
[:line
{:x1 "50.00",
:y1 "158.00",
:x2 "580.00",
:y2 "158.00",
:key "G__2312"}]
[:line
{:x1 "50.00",
:y1 "135.00",
:x2 "580.00",
:y2 "135.00",
:key "G__2313"}]
[:line
{:x1 "50.00",
:y1 "112.00",
:x2 "580.00",
:y2 "112.00",
:key "G__2314"}]
[:line
{:x1 "50.00",
:y1 "89.00",
:x2 "580.00",
:y2 "89.00",
:key "G__2315"}]
[:line
{:x1 "50.00",
:y1 "66.00",
:x2 "580.00",
:y2 "66.00",
:key "G__2316"}]
[:line
{:x1 "50.00",
:y1 "43.00",
:x2 "580.00",
:y2 "43.00",
:key "G__2317"}]
[:line
{:x1 "50.00",
:y1 "20.00",
:x2 "580.00",
:y2 "20.00",
:key "G__2318"}])]
([:polygon
{:fill "#0af",
:points
"50.00,135.00 52.65,133.25 55.30,132.15 57.95,134.87 60.60,140.39 63.25,143.96 65.90,141.29 68.55,132.58 71.20,122.96 73.85,119.11 76.50,124.66 79.15,137.62 81.80,151.35 84.45,158.32 87.10,154.21 89.75,140.13 92.40,122.00 95.05,107.68 97.70,103.45 100.35,111.46 103.00,129.08 105.65,150.21 108.30,167.65 110.95,175.64 113.60,171.61 116.25,156.65 118.90,134.91 121.55,112.13 124.20,93.97 126.85,84.67 129.50,86.15 132.15,97.89 134.80,117.33 137.45,140.65 140.10,163.61 142.75,182.43 145.40,194.32 148.05,197.82 150.70,192.80 153.35,180.30 156.00,162.20 158.65,140.85 161.30,118.69 163.95,97.97 166.60,80.51 169.25,67.63 171.90,60.05 174.55,57.96 177.20,61.12 179.85,68.92 182.50,80.52 185.15,94.95 187.80,111.23 190.45,128.41 193.10,145.63 195.75,162.19 198.40,177.51 201.05,191.18 203.70,202.93 206.35,212.61 209.00,220.19 211.65,225.72 214.30,229.30 216.95,231.12 219.60,231.35 222.25,230.21 224.90,227.91 227.55,224.66 230.20,220.66 232.85,216.09 235.50,211.11 238.15,205.86 240.80,200.48 243.45,195.07 246.10,189.71 248.75,184.48 251.40,179.44 254.05,174.63 256.70,170.08 259.35,165.81 262.00,161.85 264.65,158.20 267.30,154.86 269.95,151.83 272.60,149.11 275.25,146.68 277.90,144.54 280.55,142.67 283.20,141.05 285.85,139.67 288.50,138.52 291.15,137.57 293.80,136.81 296.45,136.22 299.10,135.77 301.75,135.44 304.40,135.23 307.05,135.10 309.70,135.03 312.35,135.00 315.00,135.00 317.65,135.00 320.30,134.97 322.95,134.90 325.60,134.77 328.25,134.56 330.90,134.23 333.55,133.78 336.20,133.19 338.85,132.43 341.50,131.48 344.15,130.33 346.80,128.95 349.45,127.33 352.10,125.46 354.75,123.32 357.40,120.89 360.05,118.17 362.70,115.14 365.35,111.80 368.00,108.15 370.65,104.19 373.30,99.92 375.95,95.37 378.60,90.56 381.25,85.52 383.90,80.29 386.55,74.93 389.20,69.52 391.85,64.14 394.50,58.89 397.15,53.91 399.80,49.34 402.45,45.34 405.10,42.09 407.75,39.79 410.40,38.65 413.05,38.88 415.70,40.70 418.35,44.28 421.00,49.81 423.65,57.39 426.30,67.07 428.95,78.82 431.60,92.49 434.25,107.81 436.90,124.37 439.55,141.59 442.20,158.77 444.85,175.05 447.50,189.48 450.15,201.08 452.80,208.88 455.45,212.04 458.10,209.95 460.75,202.37 463.40,189.49 466.05,172.03 468.70,151.31 471.35,129.15 474.00,107.80 476.65,89.70 479.30,77.20 481.95,72.18 484.60,75.68 487.25,87.57 489.90,106.39 492.55,129.35 495.20,152.67 497.85,172.11 500.50,183.85 503.15,185.33 505.80,176.03 508.45,157.87 511.10,135.09 513.75,113.35 516.40,98.39 519.05,94.36 521.70,102.35 524.35,119.79 527.00,140.92 529.65,158.54 532.30,166.55 534.95,162.32 537.60,148.00 540.25,129.87 542.90,115.79 545.55,111.68 548.20,118.65 550.85,132.38 553.50,145.34 556.15,150.89 558.80,147.04 561.45,137.42 564.10,128.71 566.75,126.04 569.40,129.61 572.05,135.13 574.70,137.85 577.35,136.75 580.00,135.00 580.00,250.00 50.00,250.00",
:key "G__2320"}])
[:g
{:stroke "black", :key "G__2337"}
([:line
{:x1 "50.00",
:y1 "250.00",
:x2 "50.00",
:y2 "260.00",
:key "G__2321"}]
[:line
{:x1 "182.50",
:y1 "250.00",
:x2 "182.50",
:y2 "260.00",
:key "G__2322"}]
[:line
{:x1 "315.00",
:y1 "250.00",
:x2 "315.00",
:y2 "260.00",
:key "G__2323"}]
[:line
{:x1 "447.50",
:y1 "250.00",
:x2 "447.50",
:y2 "260.00",
:key "G__2324"}]
[:line
{:x1 "580.00",
:y1 "250.00",
:x2 "580.00",
:y2 "260.00",
:key "G__2325"}])
([:line
{:x1 "116.25",
:y1 "250.00",
:x2 "116.25",
:y2 "255.00",
:key "G__2326"}]
[:line
{:x1 "248.75",
:y1 "250.00",
:x2 "248.75",
:y2 "255.00",
:key "G__2327"}]
[:line
{:x1 "381.25",
:y1 "250.00",
:x2 "381.25",
:y2 "255.00",
:key "G__2328"}]
[:line
{:x1 "513.75",
:y1 "250.00",
:x2 "513.75",
:y2 "255.00",
:key "G__2329"}])
[:g
{:stroke "none",
:fill "black",
:font-family "Arial, sans-serif",
:font-size 10,
:text-anchor "middle",
:key "G__2335"}
[:text {:x "50.00", :y "270.00", :key "G__2330"} "-3.14"]
[:text {:x "182.50", :y "270.00", :key "G__2331"} "-1.57"]
[:text {:x "315.00", :y "270.00", :key "G__2332"} "0.00"]
[:text {:x "447.50", :y "270.00", :key "G__2333"} "1.57"]
[:text {:x "580.00", :y "270.00", :key "G__2334"} "3.14"]]
[:line
{:x1 "50.00",
:y1 "250.00",
:x2 "580.00",
:y2 "250.00",
:key "G__2336"}]]
[:g
{:stroke "black", :key "G__2369"}
([:line
{:x1 "50.00",
:y1 "250.00",
:x2 "40.00",
:y2 "250.00",
:key "G__2338"}]
[:line
{:x1 "50.00",
:y1 "227.00",
:x2 "40.00",
:y2 "227.00",
:key "G__2339"}]
[:line
{:x1 "50.00",
:y1 "204.00",
:x2 "40.00",
:y2 "204.00",
:key "G__2340"}]
[:line
{:x1 "50.00",
:y1 "181.00",
:x2 "40.00",
:y2 "181.00",
:key "G__2341"}]
[:line
{:x1 "50.00",
:y1 "158.00",
:x2 "40.00",
:y2 "158.00",
:key "G__2342"}]
[:line
{:x1 "50.00",
:y1 "135.00",
:x2 "40.00",
:y2 "135.00",
:key "G__2343"}]
[:line
{:x1 "50.00",
:y1 "112.00",
:x2 "40.00",
:y2 "112.00",
:key "G__2344"}]
[:line
{:x1 "50.00",
:y1 "89.00",
:x2 "40.00",
:y2 "89.00",
:key "G__2345"}]
[:line
{:x1 "50.00",
:y1 "66.00",
:x2 "40.00",
:y2 "66.00",
:key "G__2346"}]
[:line
{:x1 "50.00",
:y1 "43.00",
:x2 "40.00",
:y2 "43.00",
:key "G__2347"}]
[:line
{:x1 "50.00",
:y1 "20.00",
:x2 "40.00",
:y2 "20.00",
:key "G__2348"}])
([:line
{:x1 "50.00",
:y1 "238.50",
:x2 "45.00",
:y2 "238.50",
:key "G__2349"}]
[:line
{:x1 "50.00",
:y1 "215.50",
:x2 "45.00",
:y2 "215.50",
:key "G__2350"}]
[:line
{:x1 "50.00",
:y1 "192.50",
:x2 "45.00",
:y2 "192.50",
:key "G__2351"}]
[:line
{:x1 "50.00",
:y1 "181.00",
:x2 "45.00",
:y2 "181.00",
:key "G__2352"}]
[:line
{:x1 "50.00",
:y1 "169.50",
:x2 "45.00",
:y2 "169.50",
:key "G__2353"}]
[:line
{:x1 "50.00",
:y1 "158.00",
:x2 "45.00",
:y2 "158.00",
:key "G__2354"}]
[:line
{:x1 "50.00",
:y1 "146.50",
:x2 "45.00",
:y2 "146.50",
:key "G__2355"}]
[:line
{:x1 "50.00",
:y1 "135.00",
:x2 "45.00",
:y2 "135.00",
:key "G__2356"}]
[:line
{:x1 "50.00",
:y1 "123.50",
:x2 "45.00",
:y2 "123.50",
:key "G__2357"}]
[:line
{:x1 "50.00",
:y1 "112.00",
:x2 "45.00",
:y2 "112.00",
:key "G__2358"}]
[:line
{:x1 "50.00",
:y1 "100.50",
:x2 "45.00",
:y2 "100.50",
:key "G__2359"}]
[:line
{:x1 "50.00",
:y1 "89.00",
:x2 "45.00",
:y2 "89.00",
:key "G__2360"}]
[:line
{:x1 "50.00",
:y1 "77.50",
:x2 "45.00",
:y2 "77.50",
:key "G__2361"}]
[:line
{:x1 "50.00",
:y1 "66.00",
:x2 "45.00",
:y2 "66.00",
:key "G__2362"}]
[:line
{:x1 "50.00",
:y1 "54.50",
:x2 "45.00",
:y2 "54.50",
:key "G__2363"}]
[:line
{:x1 "50.00",
:y1 "43.00",
:x2 "45.00",
:y2 "43.00",
:key "G__2364"}]
[:line
{:x1 "50.00",
:y1 "31.50",
:x2 "45.00",
:y2 "31.50",
:key "G__2365"}]
[:line
{:x1 "50.00",
:y1 "20.00",
:x2 "45.00",
:y2 "20.00",
:key "G__2366"}])
[:g
{:stroke "none",
:fill "black",
:font-family "Arial, sans-serif",
:font-size 10,
:text-anchor "middle",
:key "G__2367"}
-1
-0.8
-0.6000000000000001
-0.4000000000000001
-0.20000000000000007
-5.551115123125783e-17
0.19999999999999996
0.39999999999999997
0.6
0.8
1]
[:line
{:x1 "50.00",
:y1 "250.00",
:x2 "50.00",
:y2 "20.00",
:key "G__2368"}]]]
from geom.
That's weird - in this demo here (using Reagent) it all works perfectly: http://demo.thi.ng/ws-ldn-1/geom-viz/
will take another look tonight after the workshop...
from geom.
@postspectacular the bar chart works fine, try the line chart.
from geom.
I don't know what you're seeing with that above linked demo, but I get the same (good & expected) results in Chrome (46.0.2490.86), FF(42.0) and even Safari 6.0.5 (8536.30.1):
Screenshots from Chrome, but worrying that you seem to be seeing something else... I also don't see any React warnings in the console for any of these viz methods. What browser & version you're testing with?
If you want to try, the source for that demo is in this repo: https://github.com/thi-ng/ws-ldn-1
from geom.
Is there a way to provide a simple example of a working Reagent-based SVG for working with, say, shapes?
I'm trying the following and it's not working out:
(defn svg-component [width body]
[:div
[(->> body
(svgadapt/inject-element-attribs svgadapt/key-attrib-injector)
(svg/svg {:width width :height width}))]])
(defn simple []
(svg-component 300 (svg/group {:stroke "blue" :fill "none"} (c/circle 20))))
(defn ^:export on-js-reload []
(r/render [simple]
(js/document.getElementById "app")))
I get Error rendering component (in things.core.simple
and Uncaught Error: Invalid arity: 1
with pretty useless stack traces.
I've done my due diligence looking around the demo examples and couldn't quite find what I needed.
from geom.
Hi @Polyrhythm - there're two things wrong with your example:
- In
svg-component
- you don't want to wrap the child of the inner form in a vector, since then your structure would look like this:[:div [[:svg ... ]]]
and this causes part of the trouble - The other issue is that you forgot to call
svgadapt/all-as-svg
before injecting the:key
attribs
So corrected, this works without a hitch:
(defn svg-component [width body]
[:div
(->> body
(svgadapt/all-as-svg)
(svgadapt/inject-element-attribs svgadapt/key-attrib-injector)
(svg/svg {:width width :height width}))])
(defn simple []
(svg-component 300 (svg/group {:stroke "blue" :fill "none"} (c/circle 20))))
(defn ^:export main []
(reagent/render
[simple]
(js/document.getElementById "app")))
from geom.
@postspectacular thank you for the quick and thorough reply. Now I can get started learning this awesome set of tools. 👍
from geom.
Related Issues (20)
- README links broken
- Force Directed Graph layout HOT 1
- vector.org xforms in to vector.clj bot vector.cljs when building development branch HOT 1
- Getting error on latest clojurescript HOT 3
- question about drawing 3d objects in worldwind HOT 3
- inconsistent results in `subdivide` for rects divided six or seven times HOT 4
- ml group wants you HOT 2
- Octree gives various clojure.lang level errors HOT 11
- how to export step/igs/webgl from Obj? HOT 4
- How to create the smooth perfect mesh on 3d data points i.e. ply file using geom
- Missing IMathOps :- method for java.lang.Double when using csg/mesh->csg HOT 4
- How have you enhanced your Stacked intervals?
- Bar plots can't be drawn with a negative y-axis
- Should g/IArea always return absolute value of area?
- Handle degenerate cases in circumcircle-raw, triangle-spec
- `thi.ng.geom.polygon/tesselate*` sometimes returns nil for certain pt orderings of polygons HOT 1
- JOGL examples not working HOT 3
- Transparent (de)serialization HOT 3
- Incomplete SVG path specfication HOT 4
- Unable to specify colors per vertex
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from geom.