feat: new arguments for perpendicular method of point

This should complete all of Joyce's options for constructing
   a point by being perpendicular to something. Also fixes coloring
   of the sphere and adds the planeSlider method for constructing a
   point.
This commit is contained in:
Glen Whitney 2024-02-09 17:50:25 -08:00
parent a4f3a96d6e
commit e10da118a7

View File

@ -312,23 +312,26 @@ function jToG(
// we can adjust components after setting overall color, etc. // we can adjust components after setting overall color, etc.
// Color the "Faces"; they default to 'brighter': // Color the "Faces"; they default to 'brighter':
if invisible colors[3] if invisible(colors[3]) and (klass !== 'sphere' or invisible colors[2])
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 traceC 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 traceC 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) surface .= colors[3]
if klass is 'sphere' and invisible surface
surface = colors[2] // for Joyce, spheres had one circular "edge"
faceRGB := joyce2rgb(surface 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]
if traceC if traceC
console.log 'Coloring face', face, 'to', console.log 'Coloring face', face, 'to',
colors[3], '=', faceRGB surface, '=', faceRGB
api.setVisible face, true api.setVisible face, true
api.setFilling face, filling api.setFilling face, filling
api.setColor face, ...faceRGB api.setColor face, ...faceRGB
@ -683,12 +686,36 @@ classHandler: Record<JoyceClass, ClassHandler> :=
unless pt then return unless pt then return
commands.push `${name} = ${pt[0]} + ${pt[2]} - ${pt[1]}` commands.push `${name} = ${pt[0]} + ${pt[2]} - ${pt[1]}`
'perpendicular' 'perpendicular'
// Note only the two-point option implemented so far pt := args.subpoints
unless args.subpoints return unless pt return
inPlane := args.plane ? `,${args.plane[0]}` : defaultPlane inPlane := args.plane ? `,${args.plane[0]}` : defaultPlane
[center, direction] := args.subpoints center := pt[0]
commands.push switch pt.length
`${name} = Rotate(${direction}, pi/2, ${center}${inPlane})` when 2
commands.push
`${name} = Rotate(${pt[1]}, pi/2, ${center}${inPlane})`
when 3 // perpendicular **to** the plane
// Uses lots of auxiliaries
commands.push
`${aux}1 = Circle(${center}, Distance(${pt[1]}, ${pt[2]})${inPlane})`
`${aux}2 = PointIn(${aux}1)`
`${aux}3 = PerpendicularLine(${center}${inPlane})`
`${aux}4 = Plane(${aux}2, ${aux}3)`
`${name} = Rotate(${aux}2, pi/2, ${center}, ${aux}4)`
auxiliaries.push aux+n for n of [1..4]
when 4
commands.push
`${aux}1 = Ray(${center}, Rotate(${pt[1]}, pi/2, ${center}${inPlane}))`
`${aux}2 = Circle(${center}, Distance(${pt[2]},${pt[3]})${inPlane})`
`${name} = Intersect(${aux}1, ${aux}2)`
auxiliaries.push aux+1, aux+2
'planeSlider'
pln := args.plane?[0]
unless pln then return
commands.push `${name} = PointIn(${pln})`
if args.scalar and args.scalar.length
callbacks.push (api: AppletObject) =>
api.setCoords name, ...vertFlipped(args.scalar or [], cdata)
/proportion|similar/ /proportion|similar/
[source, displacement] := [source, displacement] :=
proportionSimilar method, args, cdata, aux, commands, auxiliaries proportionSimilar method, args, cdata, aux, commands, auxiliaries
@ -741,7 +768,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
`${aux}4 = If(${condition}, ${aux}2, ${aux}1)` `${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 aux+n for n of [1..4]
'chord' 'chord'
// To match Joyce, we need to get the ordering here correct. // To match Joyce, we need to get the ordering here correct.
// The complicated condition about distances is modeled after // The complicated condition about distances is modeled after
@ -765,7 +792,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
`${aux}4 = If(${condition}, ${aux}1, ${aux}2)` `${aux}4 = If(${condition}, ${aux}1, ${aux}2)`
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 aux+n for n of [1..4]
'connect' 'connect'
unless args.subpoints and args.subpoints.length is 2 then return unless args.subpoints and args.subpoints.length is 2 then return
ends[0] = args.subpoints[0] ends[0] = args.subpoints[0]
@ -946,7 +973,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
`${aux}1 = Angle(${pt[3]},${pt[2]},${pt[4]}${inSourcePlane})` `${aux}1 = Angle(${pt[3]},${pt[2]},${pt[4]}${inSourcePlane})`
`${aux}2 = Rotate(${pt[1]},${aux}1,${pt[0]}${inDestPlane})` `${aux}2 = Rotate(${pt[1]},${aux}1,${pt[0]}${inDestPlane})`
`${aux}3 = ${pt[0]} + (${aux}2 - ${pt[0]})*${factor}` `${aux}3 = ${pt[0]} + (${aux}2 - ${pt[0]})*${factor}`
auxiliaries.push ...[1..3].map (n) => aux + n auxiliaries.push aux+n for n of [1..3]
pt = [pt[0], pt[1], aux+3] pt = [pt[0], pt[1], aux+3]
else else
commands.push '' commands.push ''
@ -1041,8 +1068,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
`${aux}5 = ${pt[3]} + ${pt[1]} - ${pt[0]}` `${aux}5 = ${pt[3]} + ${pt[1]} - ${pt[0]}`
`${aux}6 = ${pt[3]} + ${pt[2]} - ${pt[0]}` `${aux}6 = ${pt[3]} + ${pt[2]} - ${pt[0]}`
`${aux}7 = ${pt[3]} + ${pt[2]} + ${pt[1]} - 2*${pt[0]}` `${aux}7 = ${pt[3]} + ${pt[2]} + ${pt[1]} - 2*${pt[0]}`
for i of [4..7] auxiliaries.push aux+i for i of [4..7]
auxiliaries.push aux+i
pt = [...pt, ...auxiliaries] pt = [...pt, ...auxiliaries]
parts[0].push ...pt parts[0].push ...pt
generalRecipe := generalRecipe :=
@ -1134,7 +1160,7 @@ function makeAngDiv(
`${aux}2 = Angle(${start}, ${center}, ${end}${inPlane})` `${aux}2 = Angle(${start}, ${center}, ${end}${inPlane})`
`${aux}3 = If(${aux}2 > pi, ${aux}2 - 2*pi, ${aux}2)` `${aux}3 = If(${aux}2 > pi, ${aux}2 - 2*pi, ${aux}2)`
`${aux}4 = Rotate(${start}, ${aux}3/${n}, ${center}${inPlane})` `${aux}4 = Rotate(${start}, ${aux}3/${n}, ${center}${inPlane})`
auxiliaries.push ...[2..4].map (i) => `${aux}${i}` auxiliaries.push aux+i for i of [2..4]
return {center, foot: `Intersect(${destination}, Ray(${center}, ${aux}4))`} return {center, foot: `Intersect(${destination}, Ray(${center}, ${aux}4))`}
// helper for separating color of perimeter and interior: // helper for separating color of perimeter and interior: