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