Skip to content

Commit cd93126

Browse files
committed
adding docString example
1 parent 83791c7 commit cd93126

File tree

3 files changed

+287
-0
lines changed

3 files changed

+287
-0
lines changed

src/examples/docString/index.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<html>
2+
<head>
3+
<meta charset="utf-8">
4+
<title>DocString</title>
5+
<style>
6+
body { margin: 0; }
7+
canvas { width: 100%; height: 100%; }
8+
input {width: 90%;}
9+
#container {position: relative;}
10+
#container canvas, #overlay { position: absolute;}
11+
#overlay {z-index: 1; width: 100%}
12+
13+
#loader {
14+
border: 5px solid #f3f3f3; /* Light grey */
15+
border-top: 5px solid #3d3d3d; /* Grey */
16+
border-radius: 50%;
17+
width: 40px;
18+
height: 40px;
19+
animation: spin 1s linear infinite;
20+
position: absolute;
21+
top: 50%;
22+
left: 50%;
23+
z-index: 2;
24+
}
25+
26+
@keyframes spin {
27+
0% { transform: rotate(0deg); }
28+
100% { transform: rotate(360deg); }
29+
}
30+
</style>
31+
</head>
32+
<body>
33+
<div id="loader"></div>
34+
<div id="container">
35+
<div id="overlay">
36+
<div>
37+
<input type="range" id="radius" name="radius" min="10" max="100" value="100" step="1">
38+
<label for="radius">Radius</label>
39+
</div>
40+
<div>
41+
<input type="range" id="count" name="count" min="10" max="100" value="10" step="1">
42+
<label for="count">Count</label>
43+
</div>
44+
</div>
45+
</div>
46+
<script type="module" src="./script.js"></script>
47+
</body>
48+
</html>

src/examples/docString/script.js

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/* eslint no-undef: "off", no-unused-vars: "off" */
2+
import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js'
3+
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js'
4+
import { Rhino3dmLoader } from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/3DMLoader.js'
5+
import rhino3dm from 'https://cdn.jsdelivr.net/npm/[email protected]/rhino3dm.module.js'
6+
7+
// set up loader for converting the results to threejs
8+
const loader = new Rhino3dmLoader()
9+
loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/[email protected]/' )
10+
11+
const definition = 'docString.gh'
12+
13+
// setup input change events
14+
const count_slider = document.getElementById( 'count' )
15+
count_slider .addEventListener( 'mouseup', onSliderChange, false )
16+
count_slider .addEventListener( 'touchend', onSliderChange, false )
17+
const radius_slider = document.getElementById( 'radius' )
18+
radius_slider.addEventListener( 'mouseup', onSliderChange, false )
19+
radius_slider.addEventListener( 'touchend', onSliderChange, false )
20+
21+
let rhino, doc
22+
23+
rhino3dm().then(async m => {
24+
console.log('Loaded rhino3dm.')
25+
rhino = m // global
26+
27+
init()
28+
compute()
29+
})
30+
31+
/**
32+
* Call appserver
33+
*/
34+
async function compute(){
35+
36+
// initialise 'data' object that will be used by compute()
37+
const data = {
38+
definition: definition,
39+
inputs: {
40+
'radius': radius_slider.valueAsNumber,
41+
'count': count_slider.valueAsNumber
42+
}
43+
}
44+
45+
console.log(data.inputs)
46+
47+
const request = {
48+
'method':'POST',
49+
'body': JSON.stringify(data),
50+
'headers': {'Content-Type': 'application/json'}
51+
}
52+
53+
try {
54+
const response = await fetch('/solve', request)
55+
56+
if(!response.ok)
57+
throw new Error(response.statusText)
58+
59+
const responseJson = await response.json()
60+
collectResults(responseJson)
61+
62+
} catch(error){
63+
console.error(error)
64+
}
65+
}
66+
67+
68+
// from https://stackoverflow.com/a/21797381
69+
function _base64ToArrayBuffer(base64) {
70+
var binary_string = window.atob(base64);
71+
var len = binary_string.length;
72+
var bytes = new Uint8Array(len);
73+
for (var i = 0; i < len; i++) {
74+
bytes[i] = binary_string.charCodeAt(i);
75+
}
76+
return bytes.buffer;
77+
}
78+
79+
/**
80+
* Parse response
81+
*/
82+
function collectResults(responseJson) {
83+
84+
// clear doc
85+
if (doc !== undefined)
86+
doc.delete()
87+
88+
const values = responseJson.values
89+
console.log(responseJson)
90+
91+
const str = values[0].InnerTree['{ 0; }'][0].data
92+
const data = JSON.parse(str)
93+
const arr = _base64ToArrayBuffer(data)
94+
doc = rhino.File3dm.fromByteArray(arr)
95+
96+
if (doc.objects().count < 1) {
97+
console.error('No rhino objects to load!')
98+
showSpinner(false)
99+
return
100+
}
101+
102+
// set up loader for converting the results to threejs
103+
const loader = new Rhino3dmLoader()
104+
loader.setLibraryPath('https://cdn.jsdelivr.net/npm/[email protected]/')
105+
106+
// const lineMat = new THREE.LineBasicMaterial({color: new THREE.Color('black')});
107+
// load rhino doc into three.js scene
108+
loader.parse(arr, function (object) {
109+
console.log(object)
110+
111+
scene.traverse(child => {
112+
if (child.userData.hasOwnProperty('objectType') && child.userData.objectType === 'File3dm') {
113+
scene.remove(child)
114+
}
115+
})
116+
117+
object.traverse(child => {
118+
if (child.isMesh) {
119+
const edges = new THREE.EdgesGeometry( child.geometry );
120+
const line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0x000000 } ) )
121+
child.add( line )
122+
}
123+
}, false)
124+
125+
// zoom to extents
126+
zoomCameraToSelection(camera, controls, object.children)
127+
128+
// add object graph from rhino model to three.js scene
129+
scene.add(object)
130+
131+
// hide spinner
132+
showSpinner(false)
133+
134+
})
135+
}
136+
137+
/**
138+
* Called when a slider value changes in the UI. Collect all of the
139+
* slider values and call compute to solve for a new scene
140+
*/
141+
function onSliderChange () {
142+
// show spinner
143+
showSpinner(true)
144+
compute()
145+
}
146+
147+
/**
148+
* Shows or hides the loading spinner
149+
*/
150+
function showSpinner(enable) {
151+
if (enable)
152+
document.getElementById('loader').style.display = 'block'
153+
else
154+
document.getElementById('loader').style.display = 'none'
155+
}
156+
157+
// BOILERPLATE //
158+
159+
var scene, camera, renderer, controls
160+
161+
function init () {
162+
163+
// Rhino models are z-up, so set this as the default
164+
THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 0, 1 );
165+
166+
scene = new THREE.Scene()
167+
scene.background = new THREE.Color(1,1,1)
168+
camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 1, 1000 )
169+
camera.position.x = 50
170+
camera.position.y = 50
171+
camera.position.z = 50
172+
173+
// add a directional light
174+
const directionalLight = new THREE.DirectionalLight(0xffffff)
175+
directionalLight.intensity = 2
176+
scene.add(directionalLight)
177+
178+
const ambientLight = new THREE.AmbientLight()
179+
scene.add(ambientLight)
180+
181+
renderer = new THREE.WebGLRenderer({antialias: true})
182+
renderer.setPixelRatio( window.devicePixelRatio )
183+
renderer.setSize( window.innerWidth, window.innerHeight )
184+
document.body.appendChild(renderer.domElement)
185+
186+
controls = new OrbitControls( camera, renderer.domElement )
187+
188+
window.addEventListener( 'resize', onWindowResize, false )
189+
190+
animate()
191+
}
192+
193+
var animate = function () {
194+
requestAnimationFrame( animate )
195+
renderer.render( scene, camera )
196+
}
197+
198+
function onWindowResize() {
199+
camera.aspect = window.innerWidth / window.innerHeight
200+
camera.updateProjectionMatrix()
201+
renderer.setSize( window.innerWidth, window.innerHeight )
202+
animate()
203+
}
204+
205+
/**
206+
* Helper function that behaves like rhino's "zoom to selection", but for three.js!
207+
*/
208+
function zoomCameraToSelection( camera, controls, selection, fitOffset = 1.2 ) {
209+
210+
const box = new THREE.Box3();
211+
212+
for( const object of selection ) {
213+
if (object.isLight) continue
214+
box.expandByObject( object );
215+
}
216+
217+
const size = box.getSize( new THREE.Vector3() );
218+
const center = box.getCenter( new THREE.Vector3() );
219+
220+
const maxSize = Math.max( size.x, size.y, size.z );
221+
const fitHeightDistance = maxSize / ( 2 * Math.atan( Math.PI * camera.fov / 360 ) );
222+
const fitWidthDistance = fitHeightDistance / camera.aspect;
223+
const distance = fitOffset * Math.max( fitHeightDistance, fitWidthDistance );
224+
225+
const direction = controls.target.clone()
226+
.sub( camera.position )
227+
.normalize()
228+
.multiplyScalar( distance );
229+
controls.maxDistance = distance * 10;
230+
controls.target.copy( center );
231+
232+
camera.near = distance / 100;
233+
camera.far = distance * 100;
234+
camera.updateProjectionMatrix();
235+
camera.position.copy( controls.target ).sub(direction);
236+
237+
controls.update();
238+
239+
}

src/files/docString.gh

16.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)