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:
parent
5b1ca40b26
commit
52272ff728
@ -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'
|
||||
|
Loading…
Reference in New Issue
Block a user