feat: Initial enabling of 3D

Turns on 3D viewer when needed; implements tetrahedron command. Still
   quite several commands remaining for first test construction
   (from Rostamian's incenter.html) to work.
This commit is contained in:
Glen Whitney 2023-10-07 08:55:56 -07:00
parent c99b51dafa
commit 3245db6d07
28 changed files with 29178 additions and 36 deletions

View file

@ -1,11 +1,12 @@
{AppletDescription, AdapParams, params, flags, ConfigType} from ./adapptypes.ts
{ AppletDescription, AdapParams, ConfigType,
params, flags, contains3d } from ./adapptypes.ts
// (At least some of) Joyce's pages have inline scripts that remove their
// own applet nodes, so we have to watch for them as they are added. Hence,
// this script runs at document_start, and watches for applets being added,
// setting up the joyceApplets structure as it goes
joyceApplets: AppletDescription[] := []
joyceApplets: AppletDescription[] .= []
obs := new MutationObserver (mutationList) =>
for each change of mutationList
for each newGenericNode of change.addedNodes
@ -38,13 +39,32 @@ function addScriptTag(url: string, module = false)
document.head.appendChild script
document.addEventListener "DOMContentLoaded", async =>
finalJoyceApplet := document.querySelector "applet[code='Geometry']"
if joyceApplets.length or finalJoyceApplet
finalJoyceApplets := document.querySelectorAll "applet[code='Geometry']"
if finalJoyceApplets.length
joyceApplets = []
for jApp of finalJoyceApplets
jParent := jApp.parentNode as HTMLElement
unless jParent then continue
id .= jParent.getAttribute 'id'
unless id
id = 'joyceApplet' + joyceApplets.length
jParent.setAttribute 'id', id
joyceApplets.push {
html: jApp.outerHTML,
params(jApp.children),
id,
width: parseInt(jApp.getAttribute('width') ?? '200'),
height: parseInt(jApp.getAttribute('height') ?? '200') }
if joyceApplets.length
config := await browser.storage.local.get(flags) as ConfigType
adapParams: AdapParams := {
codebase: browser.runtime.getURL('deps/GeoGebra/HTML5/5.0/webSimple'),
config,
joyceApplets }
use3d .= false
for each jApp of joyceApplets
if contains3d jApp.params
use3d = true
break
codebase .= browser.runtime.getURL 'deps/GeoGebra/HTML5/5.0/'
codebase += use3d ? 'web3d' : 'webSimple'
adapParams: AdapParams := {codebase, config, joyceApplets }
// @ts-ignore
window.wrappedJSObject.adapParams = cloneInto(adapParams, window)
addScriptTag(browser.runtime.getURL 'deps/GeoGebra/deployggb.js').then =>

View file

@ -1,6 +1,6 @@
import ./deps/jquery.js
import type {AppletObject} from ./deps/geotypes/api.ts
import {AppletDescription, AdapParams, params} from ./adapptypes.ts
import {AppletDescription, AdapParams, params, contains3d} from ./adapptypes.ts
colorsea from ./deps/colorsea.js
joyceApplets: AppletDescription[] := []
@ -46,13 +46,31 @@ function postApplets(jApplets: AppletDescription[], codebase = '')
appletOnLoad: (api: AppletObject) =>
elements: JoyceElements := {}
backgroundRGB := [255, 255, 255] as RGB
config3d := contains3d jApp.params
if config3d
worked := api.enable3D true
api.setPerspective 'T'
else
api.setPerspective 'G'
for name, value in jApp.params
dispatchJcommand api, name, value, elements, backgroundRGB
api.setCoordSystem -10, 10 + jApp.width, -10, 10 + jApp.height
api.setAxesVisible false, false
api.setGridVisible false
dispatchJcommand
api, name, value, elements, backgroundRGB, config3d
if config3d
depth .= jApp.width
if jApp.height > depth then depth = jApp.height
api.setCoordSystem
-10, 10 + jApp.width,
-10, 10 + jApp.height,
-depth - 10, depth + 10,
false
api.setAxesVisible 3, false, false, false
else
api.setCoordSystem -10, 10 + jApp.width, -10, 10 + jApp.height
api.setAxesVisible false, false
api.setGridVisible false
} as const
geoApp := new GGBApplet params
console.log 'About to inject', jApp.id, 'with', codebase
if codebase then geoApp.setHTML5Codebase codebase
geoApp.inject jApp.id
@ -110,7 +128,8 @@ function dispatchJcommand(
name: string,
value: string,
elements: JoyceElements
backgroundRGB: RGB): void
backgroundRGB: RGB,
is3d: boolean): void
switch name
'background'
newback := joyce2rgb value, backgroundRGB
@ -123,7 +142,8 @@ function dispatchJcommand(
'title'
if adapParams.config?.commands
console.log 'Setting title to', value
api.evalCommand `TitlePoint = Corner(1,1)
corner := is3d ? 'Corner(-1,1)' : 'Corner(1,1)'
api.evalCommand `TitlePoint = ${corner}
Text("${value}", TitlePoint + (2,5))`
/e\[\d+\]/
num := parseInt(name.slice(2))
@ -398,11 +418,11 @@ classHandler: Record<JoyceClass, ClassHandler> :=
`${name} = Intersect(${destination}, Ray(${center}, ${aux}4))`
auxiliaries.push ...[2..4].map (i) => `${aux}${i}`
'extend'
unless args.subpoints then return
sp := args.subpoints
unless sp then return
direction .= `UnitVector(Vector(${sp[0]},${sp[1]}))`
if args.line and (
not args.point or args.point[0] !== args.subpoints[0])
not args.point or args.point[0] !== sp[0])
direction = `UnitVector(${args.line[0]})`
displacement := `Distance(${sp[2]}, ${sp[3]})*${direction}`
commands.push `${name} = Translate(${sp[1]}, ${displacement})`
@ -410,7 +430,9 @@ classHandler: Record<JoyceClass, ClassHandler> :=
unless args.subpoints then return
commands.push `${name} = ${args.subpoints[0]}`
/fixed|free/
commands.push `${name} = (${args.scalar?.join ','})`
coords := args.scalar
unless coords then return
commands.push `${name} = (${coords.join ','})`
if method is 'fixed'
callbacks.push (api: AppletObject) => api.setFixed name, true
'foot'
@ -600,4 +622,37 @@ classHandler: Record<JoyceClass, ClassHandler> :=
plane: (name, method, args) => freshCommander()
sphere: (name, method, args) => freshCommander()
polyhedron: (name, method, args) => freshCommander()
polyhedron: (name, method, args, index) =>
return := freshCommander()
return.value.ends = ['', '']
{commands, callbacks, parts, auxiliaries, ends} := return.value
aux := name + 'aUx'
switch method
'tetrahedron'
pt := args.subpoints
unless pt and pt.length is 4 then return
commands.push '' // hack, make sure there is a command
parts[0].push ...pt
ends[0] = aux + 1
ends[1] = pt[3]
callbacks.push (api: AppletObject, moreParts: DimParts) =>
madeBase := api.evalCommandGetLabels
`${ends[0]} = Polygon(${pt[0]},${pt[1]},${pt[2]})`
if not madeBase return
for each obj of madeBase.split ','
if obj is ends[0] continue
newObj := 'GeoAux' + index + obj
api.renameObject obj, newObj
moreParts[1].push newObj
made := api.evalCommandGetLabels
`${name} = Pyramid(${aux}1, ${pt[3]})`
if not made return
for each obj of made.split ','
if obj is name continue
newObj := 'GeoAux' + index + obj
api.renameObject obj, newObj
switch api.getObjectType newObj
'segment'
moreParts[1].push newObj
'triangle'
moreParts[2].push newObj

View file

@ -23,3 +23,9 @@ export function params(kids: HTMLCollection): Record<string, string>
value := kid.getAttribute 'value'
unless name and value then continue
return.value[name] = value
prim3d := /polyhedron|sphere|plane|face/
export function contains3d(params: Record<string, string>): boolean
for value of Object.values(params)
if prim3d.test(value) then return true
return false