Last active
September 6, 2022 13:14
-
-
Save xnuk/a54c42d312d4543fab21a721e3989b68 to your computer and use it in GitHub Desktop.
GeoGebra Geometry .ggb file Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim: ts=4 | |
require "./geo.cr" | |
PI = '\u03C0' | |
Geo.render(Path["./foo.ggb"]) do | |
d "poly = 2 * pi / 7" { hidden } | |
d "r = 10" { hidden } | |
angle_hidden = false | |
d "O = Intersect(xAxis, yAxis)" | |
d "A = O + (0, r)" { hidden :label if angle_hidden } | |
d "B = Rotate(A, -poly)" { hidden :label if angle_hidden } | |
d "C = Rotate(A, -2 * poly)" { hidden :label if angle_hidden } | |
d "D = Rotate(A, -3 * poly)" { hidden :label if angle_hidden } | |
d "E = Rotate(A, 3 * poly)" { hidden :label if angle_hidden } | |
d "F = Rotate(A, 2 * poly)" { hidden :label if angle_hidden } | |
d "G = Rotate(A, poly)" { hidden :label if angle_hidden } | |
d "cir = Circle(O, r)" { hidden } | |
d "p = PolyLine(A,B,C,D,E,F,G,A)" | |
d "l1 = Segment(B,F)" { decoration :line_pp } | |
d "l1_p = Segment(A,G)" { decoration :line_pp } | |
d "l2 = Segment(A,C)" | |
d "H = Intersect(l1, l2)" | |
d "a = CircleArc(O,C,B)" do | |
show | |
line type: dash_dot | |
color 0, 0 | |
end | |
d "sixa = CircleArc(O,B,C)" { line type: long_dash, thickness: 3 } | |
angle "abf" do | |
show; caption "2a"; line opacity: 0.4 | |
offset x: -30 | |
arc_size 25 | |
end | |
angle "fbc" do | |
show; caption "3a"; line opacity: 0.4 | |
offset y: 20, x: -10 | |
arc_size 30 | |
end | |
angle "bca" do | |
show; caption "a"; line opacity: 0.4 | |
offset y: -20, x: -10 | |
end | |
angle "agf" do | |
show; caption "5a"; line opacity: 0.4 | |
offset x: 20, y: 20 | |
end | |
angle "gfb" do | |
show; caption "2a"; line opacity: 0.4 | |
offset x: 20, y: -20 | |
end | |
angle "cag" do | |
show; caption "4a"; line opacity: 0.4 | |
arc_size 40 | |
offset y: 30 | |
end | |
angle "bac" do | |
show; caption "a"; line opacity: 0.4 | |
offset x: 20, y: 17 | |
end | |
angle "bhc" do | |
show; caption "3a"; line opacity: 0.4 | |
offset x: 20 | |
arc_size 25 | |
color 0xff0000, 0.3 | |
end | |
angle "ahb" do | |
show; caption "4a"; line opacity: 0.4 | |
offset y: -20 | |
arc_size 30 | |
color 0xff0000, 0.3 | |
end | |
angle "acd" do | |
show; caption "4a"; line opacity: 0.4 | |
offset x: -35 | |
arc_size 35 | |
end | |
d "ch = Segment(C,H)" { decoration :line_s } | |
d "ab = Segment(A,B)" { decoration :line_s } | |
d "bc = Segment(B,C)" { decoration :line_s } | |
d "cd = Segment(C,D)" { decoration :line_s } | |
d "de = Segment(D,E)" { decoration :line_s } | |
d "ef = Segment(E,F)" { decoration :line_s } | |
d "fg = Segment(F,G)" { decoration :line_s } | |
d "dh = Segment(D,H)" | |
angle "dhc" do | |
show; caption "1.5a"; line opacity: 0.4 | |
offset y: 30 | |
color 0x6666ff, 0.4 | |
end | |
angle "hdc" do | |
show; caption "1.5a"; line opacity: 0.4 | |
offset y: -30 | |
color 0x6666ff, 0.4 | |
end | |
angle "hde" do | |
show; caption "3.5a = 7a/2 = #{PI}/2"; line opacity: 0.4 | |
offset x: -120, y: -30 | |
color 0x666600, 0.4 | |
arc_size 40 | |
no_right_angle | |
end | |
description = <<-'EOF' | |
회색: 원주각 | |
빨간색: 삼각형의 외각 | |
파란색: 이등변삼각형 | |
EOF | |
example = %w[ | |
\text{ex) } | |
\angle CAG = \stackrel{\large\frown}{GEC} | |
= 4 \times \stackrel{\large\frown}{BC} | |
= 4a | |
].join(' ') | |
d "description = \"#{description}\"" { start_point x: -5, y: 6 } | |
d "example = \"#{example}\"" { latex; start_point x: -6, y: 4.5 } | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# vim: ts=4 | |
require "xml" | |
require "compress/zip" | |
class Geo | |
TEMPLATE = %w{ | |
<?xml version="1.0" encoding="utf-8"?> | |
<geogebra format="5.0" version="5.0.729.0" app="geometry" | |
xsi:noNamespaceSchemaLocation="http://www.geogebra.org/apps/xsd/ggb.xsd" | |
xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<scripting blocked="true" disabled="true"/> | |
<euclidianView> | |
<evSettings axes="false" grid="false" gridIsBold="false" /> | |
</euclidianView> | |
<kernel> | |
<continuous val="false"/> | |
<usePathAndRegionParameters val="true"/> | |
<decimals val="1"/> | |
<angleUnit val="degree"/> | |
<coordStyle val="0"/> | |
</kernel> | |
<construction>{{}}</construction></geogebra> | |
}.join(' ').gsub("> <", "><") | |
enum LineType | |
Full = 5 | |
ShortDash = 10 | |
LongDash = 15 | |
Dot = 20 | |
DashDot = 30 | |
end | |
def initialize(x : XML::Builder) | |
@x = x | |
end | |
def short_dash | |
LineType::ShortDash | |
end | |
def long_dash | |
LineType::LongDash | |
end | |
def dot | |
LineType::Dot | |
end | |
def dash_dot | |
LineType::DashDot | |
end | |
def angle(label : String) : Nil | |
up = label.upcase | |
d("#{label} = Angle(#{up[0]}, #{up[1]}, #{up[2]})") | |
end | |
def angle(label : String, &block) : Nil | |
angle(label) | |
@x.element("element", type: "", label: label) do | |
with self yield | |
end | |
end | |
def d(exp : String) : Nil | |
k, v = exp.split("=", 2).map(&.strip) | |
@x.element("expression", label: k, exp: v) | |
end | |
def d(exp : String, &block) : Nil | |
k, v = exp.split("=", 2).map(&.strip) | |
@x.element("expression", label: k, exp: v) | |
@x.element("element", type: "", label: k) do | |
with self yield | |
end | |
end | |
def caption(x : String) | |
@x.element("labelMode", val: 3) | |
@x.element("caption", val: x) | |
end | |
def hidden(what : Symbol = :object) | |
show_object = what != :object | |
@x.element("show", object: show_object, label: false) | |
end | |
def show | |
@x.element("show", object: true, label: true) | |
end | |
def arc_size(val : UInt16) | |
@x.element("arcSize", val: val) | |
end | |
def color(r : UInt8, g : UInt8, b : UInt8, a : Float32 = 0.1) | |
@x.element("objColor", r: r, g: g, b: b, alpha: a) | |
end | |
def color(rgb : UInt32, alpha : Float32 = 0.1) | |
color( | |
((rgb & 0xff0000) >> 16).to_u8, | |
((rgb & 0x00ff00) >> 8).to_u8, | |
(rgb & 0x0000ff).to_u8, | |
alpha | |
) | |
end | |
def line( | |
*, | |
thickness : UInt8 = 5, | |
type : LineType = LineType::Full, | |
opacity : Float32 = 0.8 | |
) | |
@x.element("lineStyle", | |
thickness: thickness, type: type.value, | |
typeHidden: 1, opacity: (opacity * 255).round.to_u | |
) | |
end | |
def no_right_angle | |
@x.element("emphasizeRightAngle", val: false) | |
end | |
def offset(*, x : Int32 | Nil = 0, y : Int32 | Nil = 0) | |
@x.element("labelOffset", x: x, y: y) | |
end | |
DECO_LINES = | |
[:none, :line_s, :line_ss, :line_sss, :line_p, :line_pp, :line_ppp] | |
DECO_ANGLES = | |
[:none, :angle_rr, :angle_rrr, | |
:angle_s, :angle_ss, :angle_sss, :angle_up, :angle_down] | |
def decoration(ty : Symbol = :none) | |
deco = DECO_LINES.index(ty) || DECO_ANGLES.index(ty) || 0 | |
@x.element("decoration", type: deco) | |
end | |
def start_point(*, x : Float32, y : Float32, z : Float32 = 1) | |
@x.element("startPoint", x: x, y: y, z: z) | |
end | |
def latex | |
@x.element("isLaTeX", val: true) | |
@x.element("font", serif: true, sizeM: 1, size: 0, style: 0) | |
end | |
def self.render(sink : IO | Path | Nil = nil) : String | |
t = XML.build_fragment do |x| | |
d = self.new(x) | |
with d yield | |
end | |
t = TEMPLATE.sub("{{}}", t.strip) | |
unless sink.nil? | |
Compress::Zip::Writer.open(sink) do |w| | |
w.add( | |
Compress::Zip::Writer::Entry.new( | |
filename: "geogebra.xml", | |
time: Time.utc(2000, 1, 1) | |
), | |
t | |
) | |
end | |
end | |
t | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment