fix: conform to Joyce's original axis orientations (#47)

Seems to produce correct diagrams for all of Joyce Euclid up to but not including the Pythagorean Theorem (I.47), so hopefully I have managed to find and correct all of the necessary orientation flips (but I won't be shocked if I have not).

Resolves #46.

Reviewed-on: #47
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-committed-by: Glen Whitney <glen@studioinfinity.org>
This commit is contained in:
Glen Whitney 2023-11-27 03:40:04 +00:00 committed by Glen Whitney
parent 5b1ca40b26
commit 52272ff728
1 changed files with 39 additions and 29 deletions

View File

@ -49,6 +49,16 @@ adapParams: AdapParams :=
? {loader: 'https://www.geogebra.org/apps/deployggb.js', joyceApplets: []}
: JSON.parse(adapptScript.dataset.params ?? '') as AdapParams
// For accessing/setting the y coordinate of a set of coordinates:
Y := 1
Z := 2
function vertFlipped(coords: number[], cdata: ConstructionData): XYZ
coords = coords.slice()
if cdata.is3d
if coords[Z] then coords[Z] = -coords[Z]
else coords[Y] = cdata.height - coords[Y]
return coords as XYZ
type ConstructionData
id: string
bg: RGB
@ -285,12 +295,13 @@ function jToG(
api.registerObjectUpdateListener(cdata.pivot, 'pivotListener')
// Create callback to assign colors
traceC := adapParams.config?.color
console.log 'Considering coloring', name, 'with', colors if traceC
if colors.length is 4 and colors.every (color) => invisible color
cmdr.callbacks.push (api: AppletObject) => api.setVisible name, false
else // we have to decorate
dimension .= cmdr.parts.findLastIndex .includes name
cmdr.callbacks.push (api: AppletObject, parts: DimParts) =>
trace := adapParams.config?.color
// Operate in order faces, lines, point, caption so that
// we can adjust components after setting overall color, etc.
@ -298,18 +309,18 @@ function jToG(
if invisible colors[3]
for each face of parts[2]
if face is name
console.log 'Fading out interior of', face if trace
console.log 'Fading out interior of', face if traceC
// hide the interior by making it transparent
api.setFilling face, 0
else if face not in cdata.elements
console.log 'Hiding face', face if trace
console.log 'Hiding face', face if traceC
api.setVisible face, false
else
faceRGB := joyce2rgb(colors[3] or 'brighter', cdata.bg)
deep := ['circle', 'polygon', 'sector']
filling := deep.includes(klass) ? 0.7 : 0.2
for each face of parts[2]
console.log 'Coloring face', face, 'to', colors[3] if trace
console.log 'Coloring face', face, 'to', colors[3] if traceC
api.setVisible face, true
api.setFilling face, filling
api.setColor face, ...faceRGB
@ -318,17 +329,17 @@ function jToG(
if invisible colors[2]
for each line of parts[1]
if line is name or line not in cdata.elements
console.log 'Hiding line', line if trace
console.log 'Hiding line', line if traceC
api.setVisible line, false
else
lineRGB := joyce2rgb(colors[2] or 'black', cdata.bg)
for each line of parts[1]
console.log 'Coloring line', line, 'to', colors[2] if trace
console.log 'Coloring line', line, 'to', colors[2] if traceC
api.setVisible line, true
api.setColor line, ...lineRGB
// Now color the points:
if trace
if traceC
console.log
'Considering point colors for', name, 'of dimension', dimension
if invisible colors[1]
@ -336,19 +347,19 @@ function jToG(
// items:
for each point of parts[0]
if point is name or point not in cdata.elements
console.log 'Hiding point', point if trace
console.log 'Hiding point', point if traceC
api.setVisible point, false
else if dimension is 0 or colors[1] // Need to color the points
ptRGB := colors[1] ? joyce2rgb colors[1], cdata.bg
: pointDefaultRGB name, method, isPivot
for each point of parts[0]
console.log 'Coloring point', point, 'to', colors[1] if trace
console.log 'Coloring point', point, 'to', colors[1] if traceC
api.setVisible point, true
api.setColor point, ...ptRGB
// Make the caption the correct color
if invisible colors[0]
console.log 'Hiding label', name if trace
console.log 'Hiding label', name if traceC
api.setLabelVisible name, false
else if colors[dimension+1] and colors[dimension+1] is not colors[0]
// Have to make a text to provide the caption, since GeoGebra
@ -377,7 +388,7 @@ function jToG(
`(4*${ex1}+${ex2})/5`
textCmd := `${textName} = Text("${jname}", ${locationExpr})`
textCol := joyce2rgb colors[0], cdata.bg
if trace
if traceC
console.log `Making text '${textCmd}' colored`, textCol
api.evalCommand textCmd
api.setColor textName, ...textCol
@ -386,13 +397,13 @@ function jToG(
else if colors[0]
// Label gets the correct color from element
// but we had better make sure it is visible:
console.log 'Showing label', name if trace
console.log 'Showing label', name if traceC
api.setLabelVisible name, true
else
// label color is defaulting. Same as element for points, invisible
// otherwise:
show := klass is 'point'
console.log 'Setting label vis of', name, 'to', show if trace
console.log 'Setting label vis of', name, 'to', show if traceC
api.setLabelVisible name, show
cdata.elements[jname] = {otherName: name, usesCaptions, klass, cmdr.ends}
@ -563,7 +574,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
pivotData[cdata.pivot].rotatable.push name
if args.scalar and args.scalar.length
callbacks.push (api: AppletObject) =>
api.setCoords name, ...args.scalar as XYZ
api.setCoords name, ...vertFlipped(args.scalar or [], cdata)
/cutoff|extend/
pt := args.subpoints
unless pt and pt.length is 4 then return
@ -574,8 +585,8 @@ classHandler: Record<JoyceClass, ClassHandler> :=
unless args.subpoints then return
commands.push `${name} = ${args.subpoints[0]}`
/fixed|free/
coords := args.scalar
unless coords then return
unless args.scalar then return
coords := vertFlipped(args.scalar, cdata)
scoord := coords.join ','
if pivotable then pivotData[cdata.pivot].rotatable.push name
commands.push `${name} = (${scoord})`
@ -612,14 +623,14 @@ classHandler: Record<JoyceClass, ClassHandler> :=
commands.push `${name} = Point(${segment})`
if args.scalar and args.scalar.length
callbacks.push (api: AppletObject) =>
api.setCoords name, ...args.scalar as XYZ
api.setCoords name, ...vertFlipped(args.scalar or [], cdata)
'lineSlider'
pt := args.subpoints
unless pt and pt.length is 2 then return
commands.push `${name} = Point(Line(${pt[0]}, ${pt[1]}))`
if args.scalar and args.scalar.length
callbacks.push (api: AppletObject) =>
api.setCoords name, ...args.scalar as XYZ
api.setCoords name, ...vertFlipped(args.scalar or [], cdata)
'midpoint'
if args.line
commands.push `${name} = Midpoint(${args.line[0]})`
@ -634,8 +645,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
// Note only the two-point option implemented so far
unless args.subpoints return
[center, direction] := args.subpoints
// Note clockwise 90° rotation (3π/2) confirmed in Joyce source
commands.push `${name} = Rotate(${direction}, 3*pi/2, ${center})`
commands.push `${name} = Rotate(${direction}, pi/2, ${center})`
/proportion|similar/
[source, displacement] :=
proportionSimilar method, args, cdata, aux, commands, auxiliaries
@ -665,7 +675,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
'bichord'
// To match Joyce, we need to get the ordering here correct.
// we want the order so that start -> end sweeping past the
// center of the other circle is counterclockwise in the first
// center of the other circle is clockwise in the first
// circle
cr := args.circle
unless cr return
@ -676,8 +686,8 @@ classHandler: Record<JoyceClass, ClassHandler> :=
condition := (`Angle(${aux}1,${ctr[0]},${ctr[1]}${inPlane})`
+ `< Angle(${aux}2,${ctr[0]},${ctr[1]}${inPlane})`)
commands.push
`${aux}3 = If(${condition}, ${aux}2, ${aux}1)`
`${aux}4 = If(${condition}, ${aux}1, ${aux}2)`
`${aux}3 = If(${condition}, ${aux}1, ${aux}2)`
`${aux}4 = If(${condition}, ${aux}2, ${aux}1)`
ends[0] = aux + 3
ends[1] = aux + 4
auxiliaries.push ...[1..4].map (n) => aux + n
@ -748,12 +758,12 @@ classHandler: Record<JoyceClass, ClassHandler> :=
if args.line?.length is 1
ln := args.line[0]
commands.push
`${name} = Rotate(${ln}, 3*pi/2, ${pt[0]}${inPlane})`
`${name} = Rotate(${ln}, pi/2, ${pt[0]}${inPlane})`
`${aux} = Vertex(${name}, 2)`
madeSegment = true
else
commands.push
`${aux} = Rotate(${pt[1]}, 3*pi/2, ${pt[0]}${inPlane})`
`${aux} = Rotate(${pt[1]}, pi/2, ${pt[0]}${inPlane})`
when 3
return // TODO: line perpendicular to plane
when 4
@ -854,7 +864,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
else if method is 'application'
unless pt.length is 3 then return
unless args.polygon?.length is 1 then return
direction := `UnitVector(${pt[2]} - ${pt[0]})`
direction := `UnitVector(${pt[0]} - ${pt[2]})`
angle := `Angle(${pt[1]},${pt[0]},${pt[2]})`
length := `Area(${args.polygon})`
+ `/(Distance(${pt[0]},${pt[1]})*sin(${angle}))`
@ -900,12 +910,12 @@ classHandler: Record<JoyceClass, ClassHandler> :=
/arc|sector/
unless args.subpoints?.length is 3 return
parts[0].push ...args.subpoints
[center, end, start] .= args.subpoints
[center, start, end] .= args.subpoints
parms .= center + ', ' + start + ', ' + end
prefix .= 'Circular'
if method is 'arc'
temp := end
end = center
temp := start
start = center
center = temp
parms = start + ', ' + center + ', ' + end
prefix = 'Circumcircular'