From acb8ec97ddba01df64c7ec882090a5796d84c62d Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Sat, 10 Mar 2018 18:17:51 -0500 Subject: [PATCH 01/24] Attempted to add the selection of a circle and to change the color of a selected point. Neither is working currently --- src/geometry/construction/Construction.kt | 16 ++-- src/geometry/primitives/Spherical2/PointS2.kt | 1 + src/sketches/ConstructionSketch.kt | 87 +++++++------------ src/sketches/SphericalSketch.kt | 4 +- 4 files changed, 44 insertions(+), 64 deletions(-) diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index dc9f222..87d645d 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -30,17 +30,17 @@ class Construction { } // Base constructions - fun makePointS2(x: Double, y: Double, z:Double) = BaseNode(this, PointS2(x, y, z)) + fun makePointS2(x: Double, y: Double, z:Double) = BaseNode(this, PointS2(x, y, z), null) // Other constructions fun makeDiskS2(p1: INode, p2: INode, p3: INode) = - ConstructionNode(this, listOf(p1, p2, p3), ThreePointsToDiskS2()) + ConstructionNode(this, listOf(p1, p2, p3), ThreePointsToDiskS2(), null) fun makeCoaxialFamilyS2(disk1: INode, disk2: INode) = - ConstructionNode(this, listOf(disk1, disk2), TwoPointsToCoaxialFamilyS2()) + ConstructionNode(this, listOf(disk1, disk2), TwoPointsToCoaxialFamilyS2(), null) fun makeCPlaneS2(disk1: INode, disk2: INode, disk3: INode) = - ConstructionNode(this, listOf(disk1, disk2, disk3), ThreeDisksToCPlaneS2()) + ConstructionNode(this, listOf(disk1, disk2, disk3), ThreeDisksToCPlaneS2(), null) } @@ -50,6 +50,7 @@ interface INode { val outgoing : MutableList> var dirty : Boolean var visited : Boolean + var style : Any? fun getOutput() : OutputType @@ -70,11 +71,13 @@ interface INode { outgoing.forEach { it.dfsSetDirty() } } + } class BaseNode( override val construction: Construction, - var theObject: OutputType + var theObject: OutputType, + override var style : Any? = null ): INode { override var visited = false @@ -100,7 +103,8 @@ class BaseNode( class ConstructionNode( override val construction: Construction, val incoming: List>, - val algorithm: IAlgorithm + val algorithm: IAlgorithm, + override var style : Any? = null ): INode { override var visited = false diff --git a/src/geometry/primitives/Spherical2/PointS2.kt b/src/geometry/primitives/Spherical2/PointS2.kt index 02d1495..46dfddc 100644 --- a/src/geometry/primitives/Spherical2/PointS2.kt +++ b/src/geometry/primitives/Spherical2/PointS2.kt @@ -19,6 +19,7 @@ class PointS2( val x: Double, val y:Double, val z:Double + ) { /* Constructors */ diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index d52999d..6a79f7d 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -64,8 +64,6 @@ class ArcballTool(val arcball: Arcball?) : MouseTool { } open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { - // var selectedPoint : PointS2 = PointS2(0.0, 0.0, 0.0) //BaseNode = BaseNode(sketch.construction, PointS2(0.0, 0.0, 0.0)) - // var selectedPoints = mutableListOf()//mutableListOf>() var selectedNode : INode<*>? = null; var selectedNodes = mutableListOf>() @@ -75,7 +73,6 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { if (gl is PGraphicsOpenGL) { var Minv = PMatrix3D(gl.projmodelview) Minv.invert() //PVM inverted - //System.out.println("wdith " + width) var mousex = (2.0f * mouseX) / sketch.width - 1.0f var mousey = 1.0f - (2.0f * mouseY) / sketch.height @@ -118,7 +115,6 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { override fun mousePressed(mouseX: Int, mouseY: Int) { var cursor = transform(mouseX, mouseY) if (cursor != null) { - //var pointClicked = PointS2(cursor.x, cursor.y, cursor.z) for (node in sketch.construction.nodes) { if (node != null) { @@ -128,10 +124,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { if (Math.abs(cursor.x.toFloat() - output.x) <= .1 && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { -// selectedPoint = output -// selectedPoints.add(output); -// sketch.pointsDrawn.remove(selectedPoint) -// sketch.objects.remove(selectedPoint) + //TODO: change the cursor so the point is visible when being dragged selectedNode = node break } @@ -141,21 +134,6 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { } } } -// -// var iterator = sketch.pointsDrawn.listIterator() -// while (iterator.hasNext()) { -// var point = iterator.next() -// if (Math.abs(cursor.x.toFloat() - point.x) <= .1 -// && Math.abs(cursor.y.toFloat() - point.y) <= .1 -// && Math.abs(cursor.z.toFloat() - point.z) <= .1) { -// selectedPoint = point -// selectedPoints.add(point); -// sketch.pointsDrawn.remove(selectedPoint) -// sketch.objects.remove(selectedPoint) -// break -// } -// } - override fun mouseReleased(mouseX: Int, mouseY: Int) { @@ -175,7 +153,6 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { var drawNode = true var cursor = transform(mouseX, mouseY) if (cursor != null) { - //var pointClicked = PointS2(cursor.x, cursor.y, cursor.z) for (node in sketch.construction.nodes) { if(node != null) { var output = node.getOutput() @@ -184,6 +161,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { drawNode = false + node.style = Style(Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat()), Color.noColor) break } } @@ -193,23 +171,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { sketch.construction.makePointS2(cursor.x, cursor.y, cursor.z) } } -// -// var iterator = sketch.pointsDrawn.listIterator() -// var drawPoint = true -// while (iterator.hasNext()) { -// var point = iterator.next() -// if (Math.abs(cursor.x.toFloat() - point.x) <= .1 -// && Math.abs(cursor.y.toFloat() - point.y) <= .1 -// && Math.abs(cursor.z.toFloat() - point.z) <= .1) { -// drawPoint = false; -// break -// } -// } -// if (drawPoint && keyCodes != 67) { -// sketch.objects.add(pointClicked) -// sketch.pointsDrawn.add(pointClicked) -// } -// } + } class CircleTool(sketch: ConstructionSketch) : MouseTool, PointEditorTool(sketch) { @@ -217,20 +179,16 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { override fun mousePressed(mouseX: Int, mouseY: Int) { var cursor = transform(mouseX, mouseY) if (cursor != null) { - //var pointClicked = PointS2(cursor.x, cursor.y, cursor.z) for (node in sketch.construction.nodes) { if (node != null) { var output = node.getOutput() if (output is PointS2) { - //should change this so its the closet found point + //TODO: should change this so its the closet found point if (Math.abs(cursor.x.toFloat() - output.x) <= .1 && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { -// selectedPoint = output -// selectedPoints.add(output); -// sketch.pointsDrawn.remove(selectedPoint) -// sketch.objects.remove(selectedPoint) + selectedNode = node break } @@ -242,9 +200,30 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { selectedNodes.add(selectedNode as INode<*>) } + + override fun mouseClicked(mouseX: Int, mouseY: Int) { + var transformedCursor = super.transform(mouseX, mouseY) + for (node in sketch.construction.nodes) { + var x = transformedCursor.x + var y = transformedCursor.y + var z = transformedCursor.z + if(node != null) { + var output = node.getOutput() + if (output is DiskS2) { + var a = output.a + var b = output.b + var c = output.c + var d = output.d + var result = a*x + b*y + c*z + d + if(result == 0.0) { + node.style = Style(Color(255.0.toFloat(), 255.0.toFloat(), 0.0.toFloat()), Color.noColor) + } + } + } + } + } + override fun mouseReleased(mouseX: Int, mouseY: Int) { -// sketch.pointsDrawn.add(selectedPoint) - // sketch.objects.add(selectedPoint) if (selectedNodes.size >= 3) { var obj1 = selectedNodes[0] var obj2 = selectedNodes[1] @@ -255,11 +234,6 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { obj2 as INode, obj3 as INode) -// var draw = DiskS2(selectedPoints.get(0), selectedPoints.get(1), selectedPoints.get(2)) -// sketch.objects.add(draw) -// selectedPoints.removeAt(0) -// selectedPoints.removeAt(0) -// selectedPoints.removeAt(0) } } @@ -300,7 +274,6 @@ open class ConstructionSketch : SphericalSketch() { } - //val pointsDrawn = mutableListOf(); //for mouseClick() var clicked = false; var sphereCursor : PointS2? = null; @@ -343,7 +316,7 @@ open class ConstructionSketch : SphericalSketch() { ).forEach { list -> list.forEach { - val style = objectStyles[it] + val style = if(it is INode<*>) it.style as Style? else objectStyles[it] when (it) { is PointS2 -> { if (style != null) style.set(this) @@ -558,7 +531,7 @@ open class ConstructionSketch : SphericalSketch() { } override fun mousePressed() { - currentTool?.mousePressed(mouseX, mouseY)//arcball?.mousePressed() + currentTool?.mousePressed(mouseX, mouseY) } override fun mouseReleased() { diff --git a/src/sketches/SphericalSketch.kt b/src/sketches/SphericalSketch.kt index ededf63..38fb782 100644 --- a/src/sketches/SphericalSketch.kt +++ b/src/sketches/SphericalSketch.kt @@ -17,6 +17,7 @@ import geometry.construction.Construction import geometry.algorithms.incrConvexHull import geometry.algorithms.orientationPointOP3 import geometry.algorithms.addPoint +import geometry.construction.INode import geometry.ds.dcel.* import geometry.primitives.OrientedProjective2.* import geometry.primitives.isZero @@ -46,6 +47,7 @@ class Style( if (fill != null && fill != Color.noColor) p.fill(fill.x, fill.y, fill.z, fill.a) else if (fill == Color.noColor) p.noFill() } + } open class SphericalSketch : PApplet() { @@ -624,7 +626,7 @@ open class SphericalSketch : PApplet() { ).forEach { list -> list.forEach { - val style = objectStyles[it] + val style = if(it is INode<*>) it.style as Style? else objectStyles[it] when (it) { is PointS2 -> { if (style != null) style.set(this) From 8723538275d761283a341440e833a30a13ac5388 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Tue, 13 Mar 2018 07:48:53 -0400 Subject: [PATCH 02/24] Added code to calculate the intersection of a circle and attempt to change the color if "selected". Color is not changing but intersection is being calculated correctly. --- src/sketches/ConstructionSketch.kt | 81 +++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 6a79f7d..60d1b20 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -70,30 +70,30 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { fun transform(mouseX: Int, mouseY: Int): PointE3 { val gl = sketch.g - if (gl is PGraphicsOpenGL) { - var Minv = PMatrix3D(gl.projmodelview) - Minv.invert() //PVM inverted - var mousex = (2.0f * mouseX) / sketch.width - 1.0f - var mousey = 1.0f - (2.0f * mouseY) / sketch.height + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height - var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 - var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 - var new1 = PointE3( - ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), - ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), - ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() - ) + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) - var new2 = PointE3( - ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), - ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), - ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() - ) + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) - var direction = (new2 - new1).normalize() + var direction = (new2 - new1).normalize() - var l = PointE3.O - new1 + var l = PointE3.O - new1 var tca = l.dot(direction) var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) @@ -201,12 +201,44 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { selectedNodes.add(selectedNode as INode<*>) } + fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + var rayOrigin = VectorE3(new1.x, new1.y, new1.z) + var worldOrigin = VectorE3(0.0, 0.0, 0.0) + var normalVector = VectorE3(a, b, c) + var denom = direction.dot(normalVector) + var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom + return t >= 0 + } + + return false; + } + override fun mouseClicked(mouseX: Int, mouseY: Int) { - var transformedCursor = super.transform(mouseX, mouseY) for (node in sketch.construction.nodes) { - var x = transformedCursor.x - var y = transformedCursor.y - var z = transformedCursor.z + if(node != null) { var output = node.getOutput() if (output is DiskS2) { @@ -214,8 +246,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { var b = output.b var c = output.c var d = output.d - var result = a*x + b*y + c*z + d - if(result == 0.0) { + if(isIntersection(mouseX, mouseY, a, b, c, d)) { node.style = Style(Color(255.0.toFloat(), 255.0.toFloat(), 0.0.toFloat()), Color.noColor) } } From 52ff096348261d89aa31122bfd9ffb5731610cc0 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Tue, 13 Mar 2018 10:15:45 -0400 Subject: [PATCH 03/24] Fixed the color of the selection of nodes, color of selection of disks is funky. weird bug with selected point --- src/geometry/construction/Construction.kt | 17 +++++++++++------ src/sketches/ConstructionSketch.kt | 13 ++++++++----- src/sketches/SphericalSketch.kt | 8 ++++---- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index 87d645d..2ddca9a 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -22,15 +22,15 @@ class Construction { /** * @return The actual geometric objects used in this construction. These are sorted topologically based on construction dependencies. */ - fun getGeometricObjects() : MutableList { + fun getGeometricObjects(styles: HashMap? = null) : MutableList { val objList = mutableListOf() nodes.forEach { it.visited = false } - getSourceNodes().forEach { it.visit(objList) } + getSourceNodes().forEach { it.visit(objList, styles) } return objList } // Base constructions - fun makePointS2(x: Double, y: Double, z:Double) = BaseNode(this, PointS2(x, y, z), null) + fun makePointS2(x: Double, y: Double, z:Double, style:Any? = null) = BaseNode(this, PointS2(x, y, z), style) // Other constructions fun makeDiskS2(p1: INode, p2: INode, p3: INode) = @@ -54,11 +54,16 @@ interface INode { fun getOutput() : OutputType - fun visit(objList: MutableList) { + fun visit(objList: MutableList, styles: HashMap? = null) { try { - objList.add(getOutput() as Any) + val geomObj = getOutput() + val style = this.style + objList.add(geomObj as Any) + if (styles != null && style != null) { + styles[geomObj] = style + } visited = true - outgoing.forEach { if (!it.visited && it.readyToOutputQ()) it.visit(objList) } + outgoing.forEach { if (!it.visited && it.readyToOutputQ()) it.visit(objList, styles) } } catch (e: InvalidConstructionParametersException) { e.printStackTrace() } diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 60d1b20..e482793 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -161,14 +161,13 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { drawNode = false - node.style = Style(Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat()), Color.noColor) break } } } } if (drawNode) { - sketch.construction.makePointS2(cursor.x, cursor.y, cursor.z) + val node = sketch.construction.makePointS2(cursor.x, cursor.y, cursor.z) } } @@ -190,6 +189,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { && Math.abs(cursor.z.toFloat() - output.z) <= .1) { selectedNode = node + node.style = Style(Color.noColor, Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) break } } @@ -261,7 +261,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { var obj3 = selectedNodes[2] @Suppress("UNCHECKED_CAST") - sketch.construction.makeDiskS2( obj1 as INode, + var node = sketch.construction.makeDiskS2( obj1 as INode, obj2 as INode, obj3 as INode) @@ -341,13 +341,16 @@ open class ConstructionSketch : SphericalSketch() { // Draw the points synchronized(constructionLock, { + val consStyles = HashMap() listOf>( - construction.getGeometricObjects(), + construction.getGeometricObjects(consStyles), objects ).forEach { list -> list.forEach { - val style = if(it is INode<*>) it.style as Style? else objectStyles[it] + + val style = if (consStyles[it] is Style) consStyles[it] as Style else objectStyles[it] + when (it) { is PointS2 -> { if (style != null) style.set(this) diff --git a/src/sketches/SphericalSketch.kt b/src/sketches/SphericalSketch.kt index 38fb782..b611c48 100644 --- a/src/sketches/SphericalSketch.kt +++ b/src/sketches/SphericalSketch.kt @@ -29,11 +29,11 @@ import processing.opengl.PGraphicsOpenGL import javax.swing.* -class Color(val x: Float, val y: Float, val z: Float, val a: Float = 255.0f) { +class Color(val r: Float, val g: Float, val b: Float, val a: Float = 255.0f) { companion object { val noColor = Color(-1.0f, -1.0f, -1.0f, -1.0f) } - override fun equals(c: Any?) = (c is Color && c.x == x && c.y == y && c.z == z && c.a == a) + override fun equals(c: Any?) = (c is Color && c.r == r && c.g == g && c.b == b && c.a == a) } class Style( @@ -41,10 +41,10 @@ class Style( val fill: Color? ) { fun set(p: PApplet) { - if (stroke != null && stroke != Color.noColor) p.stroke(stroke.x, stroke.y, stroke.z, stroke.a) + if (stroke != null && stroke != Color.noColor) p.stroke(stroke.r, stroke.g, stroke.b, stroke.a) else if (stroke == Color.noColor) p.noStroke() - if (fill != null && fill != Color.noColor) p.fill(fill.x, fill.y, fill.z, fill.a) + if (fill != null && fill != Color.noColor) p.fill(fill.r, fill.g, fill.b, fill.a) else if (fill == Color.noColor) p.noFill() } From 2bbf84b6de18b65ff76bb393c400f0223428377e Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Mon, 19 Mar 2018 13:33:23 -0400 Subject: [PATCH 04/24] Skeleton of selection tool added --- src/geometry/construction/Construction.kt | 4 ++++ src/gui/ConstructionGUI.kt | 13 ++++++++----- src/sketches/ConstructionSketch.kt | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index 2ddca9a..ceee646 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -41,6 +41,10 @@ class Construction { fun makeCPlaneS2(disk1: INode, disk2: INode, disk3: INode) = ConstructionNode(this, listOf(disk1, disk2, disk3), ThreeDisksToCPlaneS2(), null) + + fun makeIntersectionPoint(disk1: INode, disk2: INode) { + + } } diff --git a/src/gui/ConstructionGUI.kt b/src/gui/ConstructionGUI.kt index f558ecb..23264df 100644 --- a/src/gui/ConstructionGUI.kt +++ b/src/gui/ConstructionGUI.kt @@ -1,10 +1,7 @@ package gui -import sketches.ConstructionSketch - import javax.swing.* import java.awt.* -import sketches.SphericalSketch import java.io.OutputStream import org.python.core.* @@ -15,8 +12,7 @@ import geometry.algorithms.* import org.fife.ui.rtextarea.* import org.fife.ui.rsyntaxtextarea.* -import sketches.ArcballTool -import sketches.PointEditorTool +import sketches.* /** * Created by browermb on 2/12/2018. @@ -28,6 +24,7 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { val arcballButton : JButton val pointButton : JButton val circleButton : JButton + val selectionButton : JButton init { // Build the GUI: @@ -44,10 +41,12 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { arcballButton = JButton("arcball") pointButton = JButton("point") circleButton = JButton("circle") + selectionButton = JButton("Select") buttonFlowPanel.add(arcballButton) buttonFlowPanel.add(pointButton) buttonFlowPanel.add(circleButton) + buttonFlowPanel.add(selectionButton) buttonPanel.add(buttonFlowPanel, BorderLayout.WEST) this.contentPane.add(buttonPanel, BorderLayout.PAGE_START) @@ -63,6 +62,10 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { circleButton.addActionListener { sketch.currentTool = PointEditorTool.CircleTool(sketch) } + + selectionButton.addActionListener { + sketch.currentTool = SelectionTool(sketch) + } } } diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index e482793..0b83da0 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -63,6 +63,24 @@ class ArcballTool(val arcball: Arcball?) : MouseTool { } } +class SelectionTool(val sketch : ConstructionSketch) : MouseTool { + override fun mouseClicked(mouseX: Int, mouseY: Int) { + + } + + override fun mouseDragged(mouseX: Int, mouseY: Int) { + + } + + override fun mousePressed(mouseX: Int, mouseY: Int) { + + } + + override fun mouseReleased(mouseX: Int, mouseY: Int) { + + } +} + open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { var selectedNode : INode<*>? = null; From 69ad60601542e955e795df0ef9637cbf16803c44 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Mon, 19 Mar 2018 14:09:55 -0400 Subject: [PATCH 05/24] Implemented selection tool for DiskS2 and PointS2 --- src/sketches/ConstructionSketch.kt | 156 ++++++++++++++++++++--------- 1 file changed, 107 insertions(+), 49 deletions(-) diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 0b83da0..8cf0e8a 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -64,8 +64,114 @@ class ArcballTool(val arcball: Arcball?) : MouseTool { } class SelectionTool(val sketch : ConstructionSketch) : MouseTool { - override fun mouseClicked(mouseX: Int, mouseY: Int) { + fun transform(mouseX: Int, mouseY: Int) : PointE3{ + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + + var l = PointE3.O - new1 + + var tca = l.dot(direction) + var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) + var thc = Math.sqrt(1 - d * d) + var t0 = tca - thc + var t1 = tca + thc + var inter = PointE3(0.0, 0.0, 0.0) + if (t0 > t1) { + inter = new1 + direction * t1 + return inter + } else { + inter = new1 + direction * t0 + return inter + } + } + return PointE3() + } + + fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + var rayOrigin = VectorE3(new1.x, new1.y, new1.z) + var worldOrigin = VectorE3(0.0, 0.0, 0.0) + var normalVector = VectorE3(a, b, c) + var denom = direction.dot(normalVector) + var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom + return t >= 0 + } + + return false; + } + //TODO: need to get minimum distance and then set node also add a feature to select multiple things + override fun mouseClicked(mouseX: Int, mouseY: Int) { + var cursor = transform(mouseX, mouseY) + //var selectedNode: Any? = null + if(cursor!= null) { + for(node in sketch.construction.nodes) { + var output = node.getOutput() + if(output is PointS2) { + if (Math.abs(cursor.x.toFloat() - output.x) <= .1 + && Math.abs(cursor.y.toFloat() - output.y) <= .1 + && Math.abs(cursor.z.toFloat() - output.z) <= .1) { + //TODO: change the cursor so the point is visible when being dragged + node.style = Style(Color.noColor, Color(128.0.toFloat(), 0.0.toFloat(), 128.0.toFloat())) + break + } + } + if (output is DiskS2) { + var a = output.a + var b = output.b + var c = output.c + var d = output.d + if(isIntersection(mouseX, mouseY, a, b, c, d)) { + node.style = Style(Color(255.0.toFloat(), 255.0.toFloat(), 0.0.toFloat()), Color.noColor) + break + } + } + } + } + //(selectedNode as INode<*>).style = Style() } override fun mouseDragged(mouseX: Int, mouseY: Int) { @@ -219,57 +325,9 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { selectedNodes.add(selectedNode as INode<*>) } - fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { - val gl = sketch.g - if (gl is PGraphicsOpenGL) { - var Minv = PMatrix3D(gl.projmodelview) - Minv.invert() //PVM inverted - var mousex = (2.0f * mouseX) / sketch.width - 1.0f - var mousey = 1.0f - (2.0f * mouseY) / sketch.height - - var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 - var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 - - var new1 = PointE3( - ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), - ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), - ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() - ) - - var new2 = PointE3( - ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), - ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), - ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() - ) - - var direction = (new2 - new1).normalize() - var rayOrigin = VectorE3(new1.x, new1.y, new1.z) - var worldOrigin = VectorE3(0.0, 0.0, 0.0) - var normalVector = VectorE3(a, b, c) - var denom = direction.dot(normalVector) - var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom - return t >= 0 - } - - return false; - } override fun mouseClicked(mouseX: Int, mouseY: Int) { - for (node in sketch.construction.nodes) { - if(node != null) { - var output = node.getOutput() - if (output is DiskS2) { - var a = output.a - var b = output.b - var c = output.c - var d = output.d - if(isIntersection(mouseX, mouseY, a, b, c, d)) { - node.style = Style(Color(255.0.toFloat(), 255.0.toFloat(), 0.0.toFloat()), Color.noColor) - } - } - } - } } override fun mouseReleased(mouseX: Int, mouseY: Int) { From 54932d4ee64e766abec25703a5ab6087a52919e9 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Tue, 20 Mar 2018 09:42:04 -0400 Subject: [PATCH 06/24] Implemented selection tool for DiskS2 and PointS2 --- .../construction/BasicAlgorithmsS2.kt | 31 +++++++++++++++++++ src/geometry/construction/Construction.kt | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index 1835ec7..cc201ea 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -1,6 +1,8 @@ package geometry.construction +import geometry.primitives.Euclidean3.VectorE3 import geometry.primitives.Spherical2.* +import java.awt.Point /** * Created by johnbowers on 5/28/17. @@ -55,4 +57,33 @@ class TwoPointsToCoaxialFamilyS2() : IAlgorithm { throw InvalidConstructionParametersException("TwoPointsToCoaxialFamilyS2 expects two DiskS2s.") } } +} + +class TwoDisksIntersectionPoint() : IAlgorithm { + override fun run(node: ConstructionNode): PointS2 { + if (node.incoming.size != 2) { + throw InvalidConstructionParametersException("TwoDisksIntersectionPoint expects two DiskS2s. ${node.incoming.size} given.") + } + + val disk1 = node.incoming[0].getOutput() as DiskS2 + val disk2 = node.incoming[1].getOutput() as DiskS2 + + val disk1Normal = VectorE3(disk1.a, disk1.b, disk1.c) + val disk2Normal = VectorE3(disk2.a, disk2.b, disk2.c) + val intersectionNormal = disk1Normal.cross(disk2Normal) + val point = pointOnPlanes(disk1, disk2) + + return PointS2() + + + } + + fun pointOnPlanes(disk1 : DiskS2, disk2 : DiskS2): PointS2 { + var numerator = -1*(disk1.d*disk2.a + disk1.a*disk2.d) + var denom = -1*(disk1.a*disk2.b + disk1.b*disk2.a) + var y = numerator/denom + var x = (-disk1.d - disk1.b*y)/disk1.a + + return PointS2(x, y, 0.0) + } } \ No newline at end of file diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index ceee646..fbeb28b 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -43,7 +43,7 @@ class Construction { ConstructionNode(this, listOf(disk1, disk2, disk3), ThreeDisksToCPlaneS2(), null) fun makeIntersectionPoint(disk1: INode, disk2: INode) { - + ConstructionNode(this, listOf(disk1, disk2), TwoDisksIntersectionPoint(), null) } } From 54c67eb4a2a38acb5f040adf452dc8f6c5dcb560 Mon Sep 17 00:00:00 2001 From: maddiebrower Date: Thu, 22 Mar 2018 13:15:55 -0400 Subject: [PATCH 07/24] Made changes to the mouse tool in order to account for a java bug on mac os --- src/sketches/ConstructionSketch.kt | 101 +++++++++++++++++++++++------ src/sketches/SphericalSketch.kt | 2 + 2 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 8cf0e8a..c7451ca 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -38,22 +38,60 @@ import javax.swing.* * Created by browermb on 7/27/2017. */ -var circleTool = false -interface MouseTool { - fun mousePressed(mouseX: Int, mouseY: Int) - fun mouseReleased(mouseX: Int, mouseY: Int) - fun mouseDragged(mouseX: Int, mouseY: Int) - fun mouseClicked(mouseX: Int, mouseY: Int) +open class MouseTool { + var mouseDown = false + var startX = -1 + var startY = -1 + var dragged = false + + open fun mousePressed(mouseX: Int, mouseY: Int) { + mouseDown = true + dragged = false + startX = mouseX + startY = mouseY + } + + open fun mouseReleased(mouseX: Int, mouseY: Int) { + mouseDown = false + if (!dragged) { + mouseClicked(mouseX, mouseY) + } + dragged = false + } + + open fun mouseDragged(mouseX: Int, mouseY: Int) { + + } + + open fun mouseClicked(mouseX: Int, mouseY: Int) { + } + open fun mouseMoved(mouseX: Int, mouseY: Int) { + if (mouseDown) { + val dx = mouseX - startX + val dy = mouseY - startY + + if ((dx * dx) + (dy * dy) >= 4) { + dragged = true + } + + if (dragged) { + this.mouseDragged(mouseX, mouseY) + } + } + } } -class ArcballTool(val arcball: Arcball?) : MouseTool { +class ArcballTool(val arcball: Arcball?) : MouseTool() { + override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) arcball?.mousePressed() } override fun mouseReleased(mouseX: Int, mouseY: Int) { - arcball?.mouseReleased() + super.mouseReleased(mouseX, mouseY) + arcball?.mousePressed() } override fun mouseDragged(mouseX: Int, mouseY: Int) { arcball?.mouseDragged() @@ -61,9 +99,12 @@ class ArcballTool(val arcball: Arcball?) : MouseTool { override fun mouseClicked(mouseX: Int, mouseY: Int) { } + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } } -class SelectionTool(val sketch : ConstructionSketch) : MouseTool { +class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { fun transform(mouseX: Int, mouseY: Int) : PointE3{ val gl = sketch.g if (gl is PGraphicsOpenGL) { @@ -174,20 +215,24 @@ class SelectionTool(val sketch : ConstructionSketch) : MouseTool { //(selectedNode as INode<*>).style = Style() } + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } + override fun mouseDragged(mouseX: Int, mouseY: Int) { } override fun mousePressed(mouseX: Int, mouseY: Int) { - + super.mousePressed(mouseX, mouseY) } override fun mouseReleased(mouseX: Int, mouseY: Int) { - + super.mouseReleased(mouseX, mouseY) } } -open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { +open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { var selectedNode : INode<*>? = null; var selectedNodes = mutableListOf>() @@ -236,7 +281,12 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { return PointE3() } + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } + override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) var cursor = transform(mouseX, mouseY) if (cursor != null) { @@ -259,19 +309,19 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { } } - override fun mouseReleased(mouseX: Int, mouseY: Int) { + override fun mouseReleased(mouseX: Int, mouseY: Int) { + super.mouseReleased(mouseX, mouseY) } override fun mouseDragged(mouseX: Int, mouseY: Int) { - - var cursor = transform(mouseX, mouseY) - if (cursor != null) { - var node = selectedNode - if (node is BaseNode<*>) { - node.resetBaseNodeWith(PointS2(cursor.x, cursor.y, cursor.z)) - } + var cursor = transform(mouseX, mouseY) + if (cursor != null) { + var node = selectedNode + if (node is BaseNode<*>) { + node.resetBaseNodeWith(PointS2(cursor.x, cursor.y, cursor.z)) } + } } override fun mouseClicked(mouseX: Int, mouseY: Int) { var drawNode = true @@ -297,9 +347,10 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { } - class CircleTool(sketch: ConstructionSketch) : MouseTool, PointEditorTool(sketch) { + class CircleTool(sketch: ConstructionSketch) : PointEditorTool(sketch) { override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) var cursor = transform(mouseX, mouseY) if (cursor != null) { @@ -325,12 +376,16 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool { selectedNodes.add(selectedNode as INode<*>) } + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } override fun mouseClicked(mouseX: Int, mouseY: Int) { } override fun mouseReleased(mouseX: Int, mouseY: Int) { + super.mouseReleased(mouseX, mouseY) if (selectedNodes.size >= 3) { var obj1 = selectedNodes[0] var obj2 = selectedNodes[1] @@ -636,6 +691,10 @@ open class ConstructionSketch : SphericalSketch() { return it } + override fun mouseMoved() { + currentTool?.mouseMoved(mouseX, mouseY) + } + override fun mouseClicked() { currentTool?.mouseClicked(mouseX, mouseY) } diff --git a/src/sketches/SphericalSketch.kt b/src/sketches/SphericalSketch.kt index b611c48..09623a7 100644 --- a/src/sketches/SphericalSketch.kt +++ b/src/sketches/SphericalSketch.kt @@ -763,6 +763,8 @@ open class SphericalSketch : PApplet() { /*** Mouse Handling Code ***/ + + override fun mousePressed() { arcball?.mousePressed() } From 32cd2036dd2b1f185e802ae92cc9193578cdb7cf Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Thu, 22 Mar 2018 13:17:43 -0400 Subject: [PATCH 08/24] Added code for a construction of an intersection point given two disks --- .../construction/BasicAlgorithmsS2.kt | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index cc201ea..a4e9bdd 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -60,7 +60,7 @@ class TwoPointsToCoaxialFamilyS2() : IAlgorithm { } class TwoDisksIntersectionPoint() : IAlgorithm { - override fun run(node: ConstructionNode): PointS2 { + override fun run(node: ConstructionNode): MutableList { if (node.incoming.size != 2) { throw InvalidConstructionParametersException("TwoDisksIntersectionPoint expects two DiskS2s. ${node.incoming.size} given.") } @@ -73,11 +73,43 @@ class TwoDisksIntersectionPoint() : IAlgorithm { val intersectionNormal = disk1Normal.cross(disk2Normal) val point = pointOnPlanes(disk1, disk2) - return PointS2() + val tValues = solveForTValues(intersectionNormal, point) + + val point1 = PointS2(point.x + tValues[0]*intersectionNormal.x, point.y + tValues[0]*intersectionNormal.y, + point.z + tValues[0]*intersectionNormal.z) + + + val point2 = PointS2(point.x + tValues[1]*intersectionNormal.x, point.y + tValues[1]*intersectionNormal.y, + point.z + tValues[1]*intersectionNormal.z) + + var list = mutableListOf() + list.add(point1) + list.add(point2) + + return list } + fun solveForTValues(intersectionNormal : VectorE3, point : PointS2) : MutableList{ + val bCoefficient = (2*point.x*intersectionNormal.x + 2*point.y*intersectionNormal.y + 2*point.z*intersectionNormal.z) + val aCoefficient = intersectionNormal.x*intersectionNormal.x + intersectionNormal.y*intersectionNormal.y + + intersectionNormal.z*intersectionNormal.z + val cCoefficient = point.x*point.x + point.y*point.y + point.z*point.z - 1 + val denom = 2*aCoefficient + + var t1Numerator = -bCoefficient + Math.sqrt(Math.pow(bCoefficient,2.0) - 4*aCoefficient*cCoefficient) + var t1 = t1Numerator/denom + + var t2Numerator = -bCoefficient - Math.sqrt(Math.pow(bCoefficient,2.0) - 4*aCoefficient*cCoefficient) + var t2 = t2Numerator/denom + + var list = mutableListOf() + list.add(t1) + list.add(t2) + + return list + } fun pointOnPlanes(disk1 : DiskS2, disk2 : DiskS2): PointS2 { var numerator = -1*(disk1.d*disk2.a + disk1.a*disk2.d) var denom = -1*(disk1.a*disk2.b + disk1.b*disk2.a) @@ -86,4 +118,5 @@ class TwoDisksIntersectionPoint() : IAlgorithm { return PointS2(x, y, 0.0) } + } \ No newline at end of file From 7cea07a4568af736b961cca1d5601109a4065670 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Thu, 22 Mar 2018 13:33:07 -0400 Subject: [PATCH 09/24] Added code for a construction of an intersection point given two disks --- src/geometry/construction/BasicAlgorithmsS2.kt | 8 +++----- src/geometry/construction/Construction.kt | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index a4e9bdd..d4c6798 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -59,8 +59,8 @@ class TwoPointsToCoaxialFamilyS2() : IAlgorithm { } } -class TwoDisksIntersectionPoint() : IAlgorithm { - override fun run(node: ConstructionNode): MutableList { +class TwoDisksIntersectionPoint() : IAlgorithm> { + override fun run(node: ConstructionNode>): List { if (node.incoming.size != 2) { throw InvalidConstructionParametersException("TwoDisksIntersectionPoint expects two DiskS2s. ${node.incoming.size} given.") } @@ -82,9 +82,7 @@ class TwoDisksIntersectionPoint() : IAlgorithm { val point2 = PointS2(point.x + tValues[1]*intersectionNormal.x, point.y + tValues[1]*intersectionNormal.y, point.z + tValues[1]*intersectionNormal.z) - var list = mutableListOf() - list.add(point1) - list.add(point2) + var list = listOf(point1, point2) return list diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index fbeb28b..63967e1 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -43,7 +43,7 @@ class Construction { ConstructionNode(this, listOf(disk1, disk2, disk3), ThreeDisksToCPlaneS2(), null) fun makeIntersectionPoint(disk1: INode, disk2: INode) { - ConstructionNode(this, listOf(disk1, disk2), TwoDisksIntersectionPoint(), null) + ConstructionNode>(this, listOf(disk1, disk2), TwoDisksIntersectionPoint(), null) } } From 4ce656ce5047b30def3eed60a5f507852fe9695b Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Tue, 26 Jun 2018 07:45:41 -0400 Subject: [PATCH 10/24] merge lib+builder gradle builds to single build --- build.gradle | 101 +++++++++++++++++++++ builder/build.gradle | 55 ----------- lib/build.gradle | 83 ----------------- builder/settings.gradle => settings.gradle | 0 4 files changed, 101 insertions(+), 138 deletions(-) create mode 100644 build.gradle delete mode 100644 builder/build.gradle delete mode 100644 lib/build.gradle rename builder/settings.gradle => settings.gradle (100%) diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9785ebe --- /dev/null +++ b/build.gradle @@ -0,0 +1,101 @@ +plugins { + id 'com.google.osdetector' version '1.4.0' + id 'org.jetbrains.kotlin.jvm' version '1.2.10' + id 'application' +} + +// Set the main class for application and jar building +// - set in settings.gradle or +// defined with -Pmain= in build command +mainClassName = project.findProperty('main') ?: gradle.ext.defaultClassName + +// Set default source path +sourceSets { + main.kotlin.srcDirs += 'src/' +} + +// Use maven central repository for dependencies +repositories { + mavenCentral() +} + +dependencies { + // Kotlin standard library + compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + + // KoebeLib dependencies + compile files('lib/jar/cpcore.jar') + compile 'org.antlr:antlr4:4.7.1' + compile 'org.python:jython-standalone:2.7.0' + compile 'com.fifesoft:rsyntaxtextarea:2.6.1' + compile 'org.jogamp.jogl:jogl-all-main:2.3.2' + compile 'org.jogamp.gluegen:gluegen-rt-main:2.3.2' + compile ('org.processing:core:3.3.6') { + transitive = false + } +} + +task chkLib { + group 'KoebeLib' + description 'Ensure that the jar directory exists' + + doLast { + def f = new File('lib/jar/') + if (!f.exists()) { f.mkdirs() } + } +} + +task get_nix(type:Exec, dependsOn:chkLib) { + group 'KoebeLib' + description 'Downloads CirclePack and extracts cpcore.jar; *nix' + + workingDir 'lib/jar/' + commandLine '../getCirclePack.sh' +} + +task get_win(type:Exec, dependsOn:chkLib) { + group 'KoebeLib' + description 'Downloads CirclePack and extracts cpcore.jar; Windows' + + workingDir 'lib/jar/' + commandLine 'powershell', '-ExecutionPolicy', 'RemoteSigned', '-c', '../getCirclePack.ps1' +} + +task get { + group 'KoebeLib' + description 'Detect OS for downloading CirclePack' + + if (osdetector.os == 'windows') { + dependsOn get_win + } + else { + dependsOn get_nix + } +} + +// Only retrieve CirclePack cpcore.jar if not already done +def cpcore = new File('lib/jar/cpcore.jar') +get_nix.onlyIf { !cpcore.exists() } +get_win.onlyIf { !cpcore.exists() } + +// Can't compile without cpcore.jar +compileKotlin.dependsOn(get) + +// Build jar with main class defined earlier +// Bundle all dependencies in the jar +jar { + manifest { + attributes 'Main-Class' : project['mainClassName'] + } + + from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } +} + +task run(type: JavaExec, dependsOn: jar, overwrite: true) { + description 'Runs this project as a JVM application' + group 'application' + + main project['mainClassName'] + classpath fileTree("$jar.destinationDir") +} + diff --git a/builder/build.gradle b/builder/build.gradle deleted file mode 100644 index 2a2c4bd..0000000 --- a/builder/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id 'org.jetbrains.kotlin.jvm' version '1.2.10' - id 'application' -} - -// Set the main class for application and jar building -// - set in settings.gradle or -// defined with -Pmain= in build command -mainClassName = project.findProperty('main') ?: gradle.ext.defaultClassName - -// Set default source path -sourceSets { - main.kotlin.srcDirs += '../src/' -} - -// Use maven central repository for dependencies -repositories { - mavenCentral() -} - -dependencies { - // Kotlin standard library - compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' - - // KoebeLib dependencies - compile files('../lib/jar/cpcore.jar') - compile 'org.antlr:antlr4:4.7.1' - compile 'org.python:jython-standalone:2.7.0' - compile 'com.fifesoft:rsyntaxtextarea:2.6.1' - compile 'org.jogamp.jogl:jogl-all-main:2.3.2' - compile 'org.jogamp.gluegen:gluegen-rt-main:2.3.2' - compile ('org.processing:core:3.3.6') { - transitive = false - } -} - -// Use lib gradle for downloading CirclePack cpcore.jar -task get(type:GradleBuild) { - setDir '../lib' - buildFile = '../lib/build.gradle' - tasks = ['get'] -} - -// Can't compile without cpcore.jar -compileKotlin.dependsOn(get) - -// Build jar with main class defined earlier -// Bundle all dependencies in the jar -jar { - manifest { - attributes 'Main-Class' : project['mainClassName'] - } - - from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } -} diff --git a/lib/build.gradle b/lib/build.gradle deleted file mode 100644 index a5512ef..0000000 --- a/lib/build.gradle +++ /dev/null @@ -1,83 +0,0 @@ -plugins { - id 'com.google.osdetector' version '1.4.0' -} - -configurations { - copy -} - -repositories { - mavenCentral() -} - -// Library dependencies to download -dependencies { - copy 'org.antlr:antlr4:4.7.1' - copy 'org.python:jython-standalone:2.7.0' - copy 'com.fifesoft:rsyntaxtextarea:2.6.1' - copy 'org.jogamp.jogl:jogl-all-main:2.3.2' - copy 'org.jogamp.gluegen:gluegen-rt-main:2.3.2' - copy ('org.processing:core:3.3.6') { - transitive = false - } -} - -task chkJar { - group 'KoebeLib' - description 'Ensure that the jar directory exists' - - doLast { - def f = new File('../lib/jar') - if (!f.exists()) { f.mkdirs() } - } -} - -task get_nix(type:Exec, dependsOn:chkJar) { - group 'KoebeLib' - description 'Downloads CirclePack and extracts cpcore.jar; *nix' - - workingDir 'jar' - commandLine '../getCirclePack.sh' -} - -task get_win(type:Exec, dependsOn:chkJar) { - group 'KoebeLib' - description 'Downloads CirclePack and extracts cpcore.jar; Windows' - - workingDir 'jar' - commandLine 'powershell', '-ExecutionPolicy', 'RemoteSigned', '-c', '../getCirclePack.ps1' -} - -task get { - group 'KoebeLib' - description 'Detect OS for downloading CirclePack' - - if (osdetector.os == 'windows') { - dependsOn get_win - } - else { - dependsOn get_nix - } -} - -// Only retrieve CirclePack cpcore.jar if not alread done -def cpcore = new File('../lib/jar/cpcore.jar') -get_nix.onlyIf { !cpcore.exists() } -get_win.onlyIf { !cpcore.exists() } - -task copy(type:Copy) { - group 'KoebeLib' - description 'Copy dependencies managed in MavenCentral to jar directory' - - into './jar' - from configurations.copy -} - -// Aggregate all dependency managment -task all { - group 'KoebeLib' - description 'Downloads all dependencies to jar directory.' - - dependsOn copy - dependsOn get -} diff --git a/builder/settings.gradle b/settings.gradle similarity index 100% rename from builder/settings.gradle rename to settings.gradle From 6e2bf706bbaad4aff0a23f6472eef8ee035e1696 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Tue, 26 Jun 2018 07:49:26 -0400 Subject: [PATCH 11/24] convert to standard gradle source set layout --- build.gradle | 5 ----- src/{ => main/kotlin}/com/processinghacks/arcball/Arcball.kt | 0 src/{ => main/kotlin}/geometry/IO/CirclePackIO.kt | 0 src/{ => main/kotlin}/geometry/IO/ConvexHullIO.kt | 0 .../kotlin}/geometry/algorithms/BasicTriangulations.kt | 0 src/{ => main/kotlin}/geometry/algorithms/CirclePack.kt | 0 src/{ => main/kotlin}/geometry/algorithms/ConvexHull.kt | 0 .../kotlin}/geometry/algorithms/IncrementalConvexHull.kt | 0 .../kotlin}/geometry/algorithms/InversiveVoronoi.kt | 0 src/{ => main/kotlin}/geometry/algorithms/SoapBubbles.kt | 0 .../kotlin}/geometry/construction/BasicAlgorithmsS2.kt | 0 src/{ => main/kotlin}/geometry/construction/Construction.kt | 0 src/{ => main/kotlin}/geometry/construction/IAlgorithm.kt | 0 src/{ => main/kotlin}/geometry/ds/dcel/DCEL.kt | 0 src/{ => main/kotlin}/geometry/ds/dcel/DCELH.kt | 0 src/{ => main/kotlin}/geometry/ds/dcel/DCEL_Operations.kt | 0 src/{ => main/kotlin}/geometry/ds/dcel/data/Basic2D.kt | 0 src/{ => main/kotlin}/geometry/ds/dcel/io/STL.kt | 0 src/{ => main/kotlin}/geometry/origami/TwistAndShrink.kt | 0 src/{ => main/kotlin}/geometry/primitives/CommonOps.kt | 0 src/{ => main/kotlin}/geometry/primitives/CommonTypes.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/BBoxE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/DiskE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/PointE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/PolygonE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/Predicates.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/SegmentE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean2/VectorE2.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/DirectionE3.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/DominantE3.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/PlaneE3.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/PointE3.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/SegmentE3.kt | 0 .../kotlin}/geometry/primitives/Euclidean3/VectorE3.kt | 0 .../kotlin}/geometry/primitives/ExtendedComplex/Complex.kt | 0 .../geometry/primitives/ExtendedComplex/ExtendedComplex.kt | 0 .../primitives/ExtendedComplex/RiemannProjectedPoint.kt | 0 .../geometry/primitives/OrientedProjective2/CircleArcOP2.kt | 0 .../geometry/primitives/OrientedProjective2/DiskOP2.kt | 0 .../geometry/primitives/OrientedProjective2/LineOP2.kt | 0 .../geometry/primitives/OrientedProjective2/PointOP2.kt | 0 .../geometry/primitives/OrientedProjective2/VectorOP2.kt | 0 .../geometry/primitives/OrientedProjective3/LineOP3.kt | 0 .../geometry/primitives/OrientedProjective3/PlaneOP3.kt | 0 .../geometry/primitives/OrientedProjective3/PointOP3.kt | 0 .../geometry/primitives/OrientedProjective3/VectorOP3.kt | 0 .../kotlin}/geometry/primitives/Spherical2/CPlaneS2.kt | 0 .../kotlin}/geometry/primitives/Spherical2/CircleArcS2.kt | 0 .../geometry/primitives/Spherical2/CoaxialFamilyS2.kt | 0 .../kotlin}/geometry/primitives/Spherical2/DiskS2.kt | 0 .../geometry/primitives/Spherical2/IncidencePrimitives.kt | 0 .../kotlin}/geometry/primitives/Spherical2/PointS2.kt | 0 src/{ => main/kotlin}/gui/ConstructionGUI.kt | 0 src/{ => main/kotlin}/gui/JythonFrame.kt | 0 src/{ => main/kotlin}/scripting/JythonBridge.kt | 0 src/{ => main/kotlin}/sketches/BasicArcballSketch.kt | 0 src/{ => main/kotlin}/sketches/ConstructionSketch.kt | 0 src/{ => main/kotlin}/sketches/SphericalSketch.kt | 0 src/{ => main/kotlin}/sketches/SphericalSketchTestbed.kt | 0 src/{ => main/kotlin}/sketches/TriangulationSketch.kt | 0 src/{ => main/kotlin}/sketches/VoronoiSketch.kt | 0 src/{ => main/kotlin}/tilings/algorithms/ChairTile.kt | 0 src/{ => main/kotlin}/tilings/algorithms/DCELTransform.kt | 0 src/{ => main/kotlin}/tilings/algorithms/EuclidPack.kt | 0 src/{ => main/kotlin}/tilings/algorithms/Triangulation.kt | 0 src/{ => main/kotlin}/tilings/applications/TileView.kt | 0 src/{ => main/kotlin}/tilings/ds/ChairTile.kt | 0 src/{ => main/kotlin}/tilings/ds/EdgeData.kt | 0 src/{ => main/kotlin}/tilings/ds/EscherTile.kt | 0 src/{ => main/kotlin}/tilings/ds/FaceData.kt | 0 src/{ => main/kotlin}/tilings/ds/PentagonalTwistTile.kt | 0 src/{ => main/kotlin}/tilings/ds/Tile.kt | 0 src/{ => main/kotlin}/tilings/ds/Tree.kt | 0 src/{ => main/kotlin}/tilings/ds/VertexData.kt | 0 .../kotlin}/tilings/language/algorithms/LanguageDriver.kt | 0 .../kotlin}/tilings/language/algorithms/Subdivider.kt | 0 .../kotlin}/tilings/language/algorithms/TileFactory.kt | 0 .../kotlin}/tilings/language/ds/EscherProgramNew.kt | 0 .../kotlin}/tilings/language/ds/MyEscherListener.kt | 0 src/{ => main/kotlin}/tilings/language/ds/Subdivision.kt | 0 src/{ => main/kotlin}/tilings/language/grammar/Escher.g4 | 0 src/{ => main/kotlin}/tilings/language/grammar/Escher.interp | 0 src/{ => main/kotlin}/tilings/language/grammar/Escher.tokens | 0 .../kotlin}/tilings/language/grammar/EscherBaseListener.java | 0 .../kotlin}/tilings/language/grammar/EscherBaseVisitor.java | 0 .../kotlin}/tilings/language/grammar/EscherLexer.interp | 0 .../kotlin}/tilings/language/grammar/EscherLexer.java | 0 .../kotlin}/tilings/language/grammar/EscherLexer.tokens | 0 .../kotlin}/tilings/language/grammar/EscherListener.java | 0 .../kotlin}/tilings/language/grammar/EscherParser.java | 0 .../kotlin}/tilings/language/grammar/EscherVisitor.java | 0 91 files changed, 5 deletions(-) rename src/{ => main/kotlin}/com/processinghacks/arcball/Arcball.kt (100%) rename src/{ => main/kotlin}/geometry/IO/CirclePackIO.kt (100%) rename src/{ => main/kotlin}/geometry/IO/ConvexHullIO.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/BasicTriangulations.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/CirclePack.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/ConvexHull.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/IncrementalConvexHull.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/InversiveVoronoi.kt (100%) rename src/{ => main/kotlin}/geometry/algorithms/SoapBubbles.kt (100%) rename src/{ => main/kotlin}/geometry/construction/BasicAlgorithmsS2.kt (100%) rename src/{ => main/kotlin}/geometry/construction/Construction.kt (100%) rename src/{ => main/kotlin}/geometry/construction/IAlgorithm.kt (100%) rename src/{ => main/kotlin}/geometry/ds/dcel/DCEL.kt (100%) rename src/{ => main/kotlin}/geometry/ds/dcel/DCELH.kt (100%) rename src/{ => main/kotlin}/geometry/ds/dcel/DCEL_Operations.kt (100%) rename src/{ => main/kotlin}/geometry/ds/dcel/data/Basic2D.kt (100%) rename src/{ => main/kotlin}/geometry/ds/dcel/io/STL.kt (100%) rename src/{ => main/kotlin}/geometry/origami/TwistAndShrink.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/CommonOps.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/CommonTypes.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/BBoxE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/DiskE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/PointE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/PolygonE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/Predicates.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/SegmentE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean2/VectorE2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/DirectionE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/DominantE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/PlaneE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/PointE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/SegmentE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Euclidean3/VectorE3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/ExtendedComplex/Complex.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/ExtendedComplex/ExtendedComplex.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/ExtendedComplex/RiemannProjectedPoint.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective2/CircleArcOP2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective2/DiskOP2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective2/LineOP2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective2/PointOP2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective2/VectorOP2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective3/LineOP3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective3/PlaneOP3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective3/PointOP3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/OrientedProjective3/VectorOP3.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/CPlaneS2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/CircleArcS2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/CoaxialFamilyS2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/DiskS2.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/IncidencePrimitives.kt (100%) rename src/{ => main/kotlin}/geometry/primitives/Spherical2/PointS2.kt (100%) rename src/{ => main/kotlin}/gui/ConstructionGUI.kt (100%) rename src/{ => main/kotlin}/gui/JythonFrame.kt (100%) rename src/{ => main/kotlin}/scripting/JythonBridge.kt (100%) rename src/{ => main/kotlin}/sketches/BasicArcballSketch.kt (100%) rename src/{ => main/kotlin}/sketches/ConstructionSketch.kt (100%) rename src/{ => main/kotlin}/sketches/SphericalSketch.kt (100%) rename src/{ => main/kotlin}/sketches/SphericalSketchTestbed.kt (100%) rename src/{ => main/kotlin}/sketches/TriangulationSketch.kt (100%) rename src/{ => main/kotlin}/sketches/VoronoiSketch.kt (100%) rename src/{ => main/kotlin}/tilings/algorithms/ChairTile.kt (100%) rename src/{ => main/kotlin}/tilings/algorithms/DCELTransform.kt (100%) rename src/{ => main/kotlin}/tilings/algorithms/EuclidPack.kt (100%) rename src/{ => main/kotlin}/tilings/algorithms/Triangulation.kt (100%) rename src/{ => main/kotlin}/tilings/applications/TileView.kt (100%) rename src/{ => main/kotlin}/tilings/ds/ChairTile.kt (100%) rename src/{ => main/kotlin}/tilings/ds/EdgeData.kt (100%) rename src/{ => main/kotlin}/tilings/ds/EscherTile.kt (100%) rename src/{ => main/kotlin}/tilings/ds/FaceData.kt (100%) rename src/{ => main/kotlin}/tilings/ds/PentagonalTwistTile.kt (100%) rename src/{ => main/kotlin}/tilings/ds/Tile.kt (100%) rename src/{ => main/kotlin}/tilings/ds/Tree.kt (100%) rename src/{ => main/kotlin}/tilings/ds/VertexData.kt (100%) rename src/{ => main/kotlin}/tilings/language/algorithms/LanguageDriver.kt (100%) rename src/{ => main/kotlin}/tilings/language/algorithms/Subdivider.kt (100%) rename src/{ => main/kotlin}/tilings/language/algorithms/TileFactory.kt (100%) rename src/{ => main/kotlin}/tilings/language/ds/EscherProgramNew.kt (100%) rename src/{ => main/kotlin}/tilings/language/ds/MyEscherListener.kt (100%) rename src/{ => main/kotlin}/tilings/language/ds/Subdivision.kt (100%) rename src/{ => main/kotlin}/tilings/language/grammar/Escher.g4 (100%) rename src/{ => main/kotlin}/tilings/language/grammar/Escher.interp (100%) rename src/{ => main/kotlin}/tilings/language/grammar/Escher.tokens (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherBaseListener.java (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherBaseVisitor.java (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherLexer.interp (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherLexer.java (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherLexer.tokens (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherListener.java (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherParser.java (100%) rename src/{ => main/kotlin}/tilings/language/grammar/EscherVisitor.java (100%) diff --git a/build.gradle b/build.gradle index 9785ebe..4eae9c2 100644 --- a/build.gradle +++ b/build.gradle @@ -9,11 +9,6 @@ plugins { // defined with -Pmain= in build command mainClassName = project.findProperty('main') ?: gradle.ext.defaultClassName -// Set default source path -sourceSets { - main.kotlin.srcDirs += 'src/' -} - // Use maven central repository for dependencies repositories { mavenCentral() diff --git a/src/com/processinghacks/arcball/Arcball.kt b/src/main/kotlin/com/processinghacks/arcball/Arcball.kt similarity index 100% rename from src/com/processinghacks/arcball/Arcball.kt rename to src/main/kotlin/com/processinghacks/arcball/Arcball.kt diff --git a/src/geometry/IO/CirclePackIO.kt b/src/main/kotlin/geometry/IO/CirclePackIO.kt similarity index 100% rename from src/geometry/IO/CirclePackIO.kt rename to src/main/kotlin/geometry/IO/CirclePackIO.kt diff --git a/src/geometry/IO/ConvexHullIO.kt b/src/main/kotlin/geometry/IO/ConvexHullIO.kt similarity index 100% rename from src/geometry/IO/ConvexHullIO.kt rename to src/main/kotlin/geometry/IO/ConvexHullIO.kt diff --git a/src/geometry/algorithms/BasicTriangulations.kt b/src/main/kotlin/geometry/algorithms/BasicTriangulations.kt similarity index 100% rename from src/geometry/algorithms/BasicTriangulations.kt rename to src/main/kotlin/geometry/algorithms/BasicTriangulations.kt diff --git a/src/geometry/algorithms/CirclePack.kt b/src/main/kotlin/geometry/algorithms/CirclePack.kt similarity index 100% rename from src/geometry/algorithms/CirclePack.kt rename to src/main/kotlin/geometry/algorithms/CirclePack.kt diff --git a/src/geometry/algorithms/ConvexHull.kt b/src/main/kotlin/geometry/algorithms/ConvexHull.kt similarity index 100% rename from src/geometry/algorithms/ConvexHull.kt rename to src/main/kotlin/geometry/algorithms/ConvexHull.kt diff --git a/src/geometry/algorithms/IncrementalConvexHull.kt b/src/main/kotlin/geometry/algorithms/IncrementalConvexHull.kt similarity index 100% rename from src/geometry/algorithms/IncrementalConvexHull.kt rename to src/main/kotlin/geometry/algorithms/IncrementalConvexHull.kt diff --git a/src/geometry/algorithms/InversiveVoronoi.kt b/src/main/kotlin/geometry/algorithms/InversiveVoronoi.kt similarity index 100% rename from src/geometry/algorithms/InversiveVoronoi.kt rename to src/main/kotlin/geometry/algorithms/InversiveVoronoi.kt diff --git a/src/geometry/algorithms/SoapBubbles.kt b/src/main/kotlin/geometry/algorithms/SoapBubbles.kt similarity index 100% rename from src/geometry/algorithms/SoapBubbles.kt rename to src/main/kotlin/geometry/algorithms/SoapBubbles.kt diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/main/kotlin/geometry/construction/BasicAlgorithmsS2.kt similarity index 100% rename from src/geometry/construction/BasicAlgorithmsS2.kt rename to src/main/kotlin/geometry/construction/BasicAlgorithmsS2.kt diff --git a/src/geometry/construction/Construction.kt b/src/main/kotlin/geometry/construction/Construction.kt similarity index 100% rename from src/geometry/construction/Construction.kt rename to src/main/kotlin/geometry/construction/Construction.kt diff --git a/src/geometry/construction/IAlgorithm.kt b/src/main/kotlin/geometry/construction/IAlgorithm.kt similarity index 100% rename from src/geometry/construction/IAlgorithm.kt rename to src/main/kotlin/geometry/construction/IAlgorithm.kt diff --git a/src/geometry/ds/dcel/DCEL.kt b/src/main/kotlin/geometry/ds/dcel/DCEL.kt similarity index 100% rename from src/geometry/ds/dcel/DCEL.kt rename to src/main/kotlin/geometry/ds/dcel/DCEL.kt diff --git a/src/geometry/ds/dcel/DCELH.kt b/src/main/kotlin/geometry/ds/dcel/DCELH.kt similarity index 100% rename from src/geometry/ds/dcel/DCELH.kt rename to src/main/kotlin/geometry/ds/dcel/DCELH.kt diff --git a/src/geometry/ds/dcel/DCEL_Operations.kt b/src/main/kotlin/geometry/ds/dcel/DCEL_Operations.kt similarity index 100% rename from src/geometry/ds/dcel/DCEL_Operations.kt rename to src/main/kotlin/geometry/ds/dcel/DCEL_Operations.kt diff --git a/src/geometry/ds/dcel/data/Basic2D.kt b/src/main/kotlin/geometry/ds/dcel/data/Basic2D.kt similarity index 100% rename from src/geometry/ds/dcel/data/Basic2D.kt rename to src/main/kotlin/geometry/ds/dcel/data/Basic2D.kt diff --git a/src/geometry/ds/dcel/io/STL.kt b/src/main/kotlin/geometry/ds/dcel/io/STL.kt similarity index 100% rename from src/geometry/ds/dcel/io/STL.kt rename to src/main/kotlin/geometry/ds/dcel/io/STL.kt diff --git a/src/geometry/origami/TwistAndShrink.kt b/src/main/kotlin/geometry/origami/TwistAndShrink.kt similarity index 100% rename from src/geometry/origami/TwistAndShrink.kt rename to src/main/kotlin/geometry/origami/TwistAndShrink.kt diff --git a/src/geometry/primitives/CommonOps.kt b/src/main/kotlin/geometry/primitives/CommonOps.kt similarity index 100% rename from src/geometry/primitives/CommonOps.kt rename to src/main/kotlin/geometry/primitives/CommonOps.kt diff --git a/src/geometry/primitives/CommonTypes.kt b/src/main/kotlin/geometry/primitives/CommonTypes.kt similarity index 100% rename from src/geometry/primitives/CommonTypes.kt rename to src/main/kotlin/geometry/primitives/CommonTypes.kt diff --git a/src/geometry/primitives/Euclidean2/BBoxE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/BBoxE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/BBoxE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/BBoxE2.kt diff --git a/src/geometry/primitives/Euclidean2/DiskE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/DiskE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/DiskE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/DiskE2.kt diff --git a/src/geometry/primitives/Euclidean2/PointE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/PointE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/PointE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/PointE2.kt diff --git a/src/geometry/primitives/Euclidean2/PolygonE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/PolygonE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/PolygonE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/PolygonE2.kt diff --git a/src/geometry/primitives/Euclidean2/Predicates.kt b/src/main/kotlin/geometry/primitives/Euclidean2/Predicates.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/Predicates.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/Predicates.kt diff --git a/src/geometry/primitives/Euclidean2/SegmentE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/SegmentE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/SegmentE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/SegmentE2.kt diff --git a/src/geometry/primitives/Euclidean2/VectorE2.kt b/src/main/kotlin/geometry/primitives/Euclidean2/VectorE2.kt similarity index 100% rename from src/geometry/primitives/Euclidean2/VectorE2.kt rename to src/main/kotlin/geometry/primitives/Euclidean2/VectorE2.kt diff --git a/src/geometry/primitives/Euclidean3/DirectionE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/DirectionE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/DirectionE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/DirectionE3.kt diff --git a/src/geometry/primitives/Euclidean3/DominantE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/DominantE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/DominantE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/DominantE3.kt diff --git a/src/geometry/primitives/Euclidean3/PlaneE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/PlaneE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/PlaneE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/PlaneE3.kt diff --git a/src/geometry/primitives/Euclidean3/PointE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/PointE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/PointE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/PointE3.kt diff --git a/src/geometry/primitives/Euclidean3/SegmentE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/SegmentE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/SegmentE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/SegmentE3.kt diff --git a/src/geometry/primitives/Euclidean3/VectorE3.kt b/src/main/kotlin/geometry/primitives/Euclidean3/VectorE3.kt similarity index 100% rename from src/geometry/primitives/Euclidean3/VectorE3.kt rename to src/main/kotlin/geometry/primitives/Euclidean3/VectorE3.kt diff --git a/src/geometry/primitives/ExtendedComplex/Complex.kt b/src/main/kotlin/geometry/primitives/ExtendedComplex/Complex.kt similarity index 100% rename from src/geometry/primitives/ExtendedComplex/Complex.kt rename to src/main/kotlin/geometry/primitives/ExtendedComplex/Complex.kt diff --git a/src/geometry/primitives/ExtendedComplex/ExtendedComplex.kt b/src/main/kotlin/geometry/primitives/ExtendedComplex/ExtendedComplex.kt similarity index 100% rename from src/geometry/primitives/ExtendedComplex/ExtendedComplex.kt rename to src/main/kotlin/geometry/primitives/ExtendedComplex/ExtendedComplex.kt diff --git a/src/geometry/primitives/ExtendedComplex/RiemannProjectedPoint.kt b/src/main/kotlin/geometry/primitives/ExtendedComplex/RiemannProjectedPoint.kt similarity index 100% rename from src/geometry/primitives/ExtendedComplex/RiemannProjectedPoint.kt rename to src/main/kotlin/geometry/primitives/ExtendedComplex/RiemannProjectedPoint.kt diff --git a/src/geometry/primitives/OrientedProjective2/CircleArcOP2.kt b/src/main/kotlin/geometry/primitives/OrientedProjective2/CircleArcOP2.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective2/CircleArcOP2.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective2/CircleArcOP2.kt diff --git a/src/geometry/primitives/OrientedProjective2/DiskOP2.kt b/src/main/kotlin/geometry/primitives/OrientedProjective2/DiskOP2.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective2/DiskOP2.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective2/DiskOP2.kt diff --git a/src/geometry/primitives/OrientedProjective2/LineOP2.kt b/src/main/kotlin/geometry/primitives/OrientedProjective2/LineOP2.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective2/LineOP2.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective2/LineOP2.kt diff --git a/src/geometry/primitives/OrientedProjective2/PointOP2.kt b/src/main/kotlin/geometry/primitives/OrientedProjective2/PointOP2.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective2/PointOP2.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective2/PointOP2.kt diff --git a/src/geometry/primitives/OrientedProjective2/VectorOP2.kt b/src/main/kotlin/geometry/primitives/OrientedProjective2/VectorOP2.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective2/VectorOP2.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective2/VectorOP2.kt diff --git a/src/geometry/primitives/OrientedProjective3/LineOP3.kt b/src/main/kotlin/geometry/primitives/OrientedProjective3/LineOP3.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective3/LineOP3.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective3/LineOP3.kt diff --git a/src/geometry/primitives/OrientedProjective3/PlaneOP3.kt b/src/main/kotlin/geometry/primitives/OrientedProjective3/PlaneOP3.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective3/PlaneOP3.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective3/PlaneOP3.kt diff --git a/src/geometry/primitives/OrientedProjective3/PointOP3.kt b/src/main/kotlin/geometry/primitives/OrientedProjective3/PointOP3.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective3/PointOP3.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective3/PointOP3.kt diff --git a/src/geometry/primitives/OrientedProjective3/VectorOP3.kt b/src/main/kotlin/geometry/primitives/OrientedProjective3/VectorOP3.kt similarity index 100% rename from src/geometry/primitives/OrientedProjective3/VectorOP3.kt rename to src/main/kotlin/geometry/primitives/OrientedProjective3/VectorOP3.kt diff --git a/src/geometry/primitives/Spherical2/CPlaneS2.kt b/src/main/kotlin/geometry/primitives/Spherical2/CPlaneS2.kt similarity index 100% rename from src/geometry/primitives/Spherical2/CPlaneS2.kt rename to src/main/kotlin/geometry/primitives/Spherical2/CPlaneS2.kt diff --git a/src/geometry/primitives/Spherical2/CircleArcS2.kt b/src/main/kotlin/geometry/primitives/Spherical2/CircleArcS2.kt similarity index 100% rename from src/geometry/primitives/Spherical2/CircleArcS2.kt rename to src/main/kotlin/geometry/primitives/Spherical2/CircleArcS2.kt diff --git a/src/geometry/primitives/Spherical2/CoaxialFamilyS2.kt b/src/main/kotlin/geometry/primitives/Spherical2/CoaxialFamilyS2.kt similarity index 100% rename from src/geometry/primitives/Spherical2/CoaxialFamilyS2.kt rename to src/main/kotlin/geometry/primitives/Spherical2/CoaxialFamilyS2.kt diff --git a/src/geometry/primitives/Spherical2/DiskS2.kt b/src/main/kotlin/geometry/primitives/Spherical2/DiskS2.kt similarity index 100% rename from src/geometry/primitives/Spherical2/DiskS2.kt rename to src/main/kotlin/geometry/primitives/Spherical2/DiskS2.kt diff --git a/src/geometry/primitives/Spherical2/IncidencePrimitives.kt b/src/main/kotlin/geometry/primitives/Spherical2/IncidencePrimitives.kt similarity index 100% rename from src/geometry/primitives/Spherical2/IncidencePrimitives.kt rename to src/main/kotlin/geometry/primitives/Spherical2/IncidencePrimitives.kt diff --git a/src/geometry/primitives/Spherical2/PointS2.kt b/src/main/kotlin/geometry/primitives/Spherical2/PointS2.kt similarity index 100% rename from src/geometry/primitives/Spherical2/PointS2.kt rename to src/main/kotlin/geometry/primitives/Spherical2/PointS2.kt diff --git a/src/gui/ConstructionGUI.kt b/src/main/kotlin/gui/ConstructionGUI.kt similarity index 100% rename from src/gui/ConstructionGUI.kt rename to src/main/kotlin/gui/ConstructionGUI.kt diff --git a/src/gui/JythonFrame.kt b/src/main/kotlin/gui/JythonFrame.kt similarity index 100% rename from src/gui/JythonFrame.kt rename to src/main/kotlin/gui/JythonFrame.kt diff --git a/src/scripting/JythonBridge.kt b/src/main/kotlin/scripting/JythonBridge.kt similarity index 100% rename from src/scripting/JythonBridge.kt rename to src/main/kotlin/scripting/JythonBridge.kt diff --git a/src/sketches/BasicArcballSketch.kt b/src/main/kotlin/sketches/BasicArcballSketch.kt similarity index 100% rename from src/sketches/BasicArcballSketch.kt rename to src/main/kotlin/sketches/BasicArcballSketch.kt diff --git a/src/sketches/ConstructionSketch.kt b/src/main/kotlin/sketches/ConstructionSketch.kt similarity index 100% rename from src/sketches/ConstructionSketch.kt rename to src/main/kotlin/sketches/ConstructionSketch.kt diff --git a/src/sketches/SphericalSketch.kt b/src/main/kotlin/sketches/SphericalSketch.kt similarity index 100% rename from src/sketches/SphericalSketch.kt rename to src/main/kotlin/sketches/SphericalSketch.kt diff --git a/src/sketches/SphericalSketchTestbed.kt b/src/main/kotlin/sketches/SphericalSketchTestbed.kt similarity index 100% rename from src/sketches/SphericalSketchTestbed.kt rename to src/main/kotlin/sketches/SphericalSketchTestbed.kt diff --git a/src/sketches/TriangulationSketch.kt b/src/main/kotlin/sketches/TriangulationSketch.kt similarity index 100% rename from src/sketches/TriangulationSketch.kt rename to src/main/kotlin/sketches/TriangulationSketch.kt diff --git a/src/sketches/VoronoiSketch.kt b/src/main/kotlin/sketches/VoronoiSketch.kt similarity index 100% rename from src/sketches/VoronoiSketch.kt rename to src/main/kotlin/sketches/VoronoiSketch.kt diff --git a/src/tilings/algorithms/ChairTile.kt b/src/main/kotlin/tilings/algorithms/ChairTile.kt similarity index 100% rename from src/tilings/algorithms/ChairTile.kt rename to src/main/kotlin/tilings/algorithms/ChairTile.kt diff --git a/src/tilings/algorithms/DCELTransform.kt b/src/main/kotlin/tilings/algorithms/DCELTransform.kt similarity index 100% rename from src/tilings/algorithms/DCELTransform.kt rename to src/main/kotlin/tilings/algorithms/DCELTransform.kt diff --git a/src/tilings/algorithms/EuclidPack.kt b/src/main/kotlin/tilings/algorithms/EuclidPack.kt similarity index 100% rename from src/tilings/algorithms/EuclidPack.kt rename to src/main/kotlin/tilings/algorithms/EuclidPack.kt diff --git a/src/tilings/algorithms/Triangulation.kt b/src/main/kotlin/tilings/algorithms/Triangulation.kt similarity index 100% rename from src/tilings/algorithms/Triangulation.kt rename to src/main/kotlin/tilings/algorithms/Triangulation.kt diff --git a/src/tilings/applications/TileView.kt b/src/main/kotlin/tilings/applications/TileView.kt similarity index 100% rename from src/tilings/applications/TileView.kt rename to src/main/kotlin/tilings/applications/TileView.kt diff --git a/src/tilings/ds/ChairTile.kt b/src/main/kotlin/tilings/ds/ChairTile.kt similarity index 100% rename from src/tilings/ds/ChairTile.kt rename to src/main/kotlin/tilings/ds/ChairTile.kt diff --git a/src/tilings/ds/EdgeData.kt b/src/main/kotlin/tilings/ds/EdgeData.kt similarity index 100% rename from src/tilings/ds/EdgeData.kt rename to src/main/kotlin/tilings/ds/EdgeData.kt diff --git a/src/tilings/ds/EscherTile.kt b/src/main/kotlin/tilings/ds/EscherTile.kt similarity index 100% rename from src/tilings/ds/EscherTile.kt rename to src/main/kotlin/tilings/ds/EscherTile.kt diff --git a/src/tilings/ds/FaceData.kt b/src/main/kotlin/tilings/ds/FaceData.kt similarity index 100% rename from src/tilings/ds/FaceData.kt rename to src/main/kotlin/tilings/ds/FaceData.kt diff --git a/src/tilings/ds/PentagonalTwistTile.kt b/src/main/kotlin/tilings/ds/PentagonalTwistTile.kt similarity index 100% rename from src/tilings/ds/PentagonalTwistTile.kt rename to src/main/kotlin/tilings/ds/PentagonalTwistTile.kt diff --git a/src/tilings/ds/Tile.kt b/src/main/kotlin/tilings/ds/Tile.kt similarity index 100% rename from src/tilings/ds/Tile.kt rename to src/main/kotlin/tilings/ds/Tile.kt diff --git a/src/tilings/ds/Tree.kt b/src/main/kotlin/tilings/ds/Tree.kt similarity index 100% rename from src/tilings/ds/Tree.kt rename to src/main/kotlin/tilings/ds/Tree.kt diff --git a/src/tilings/ds/VertexData.kt b/src/main/kotlin/tilings/ds/VertexData.kt similarity index 100% rename from src/tilings/ds/VertexData.kt rename to src/main/kotlin/tilings/ds/VertexData.kt diff --git a/src/tilings/language/algorithms/LanguageDriver.kt b/src/main/kotlin/tilings/language/algorithms/LanguageDriver.kt similarity index 100% rename from src/tilings/language/algorithms/LanguageDriver.kt rename to src/main/kotlin/tilings/language/algorithms/LanguageDriver.kt diff --git a/src/tilings/language/algorithms/Subdivider.kt b/src/main/kotlin/tilings/language/algorithms/Subdivider.kt similarity index 100% rename from src/tilings/language/algorithms/Subdivider.kt rename to src/main/kotlin/tilings/language/algorithms/Subdivider.kt diff --git a/src/tilings/language/algorithms/TileFactory.kt b/src/main/kotlin/tilings/language/algorithms/TileFactory.kt similarity index 100% rename from src/tilings/language/algorithms/TileFactory.kt rename to src/main/kotlin/tilings/language/algorithms/TileFactory.kt diff --git a/src/tilings/language/ds/EscherProgramNew.kt b/src/main/kotlin/tilings/language/ds/EscherProgramNew.kt similarity index 100% rename from src/tilings/language/ds/EscherProgramNew.kt rename to src/main/kotlin/tilings/language/ds/EscherProgramNew.kt diff --git a/src/tilings/language/ds/MyEscherListener.kt b/src/main/kotlin/tilings/language/ds/MyEscherListener.kt similarity index 100% rename from src/tilings/language/ds/MyEscherListener.kt rename to src/main/kotlin/tilings/language/ds/MyEscherListener.kt diff --git a/src/tilings/language/ds/Subdivision.kt b/src/main/kotlin/tilings/language/ds/Subdivision.kt similarity index 100% rename from src/tilings/language/ds/Subdivision.kt rename to src/main/kotlin/tilings/language/ds/Subdivision.kt diff --git a/src/tilings/language/grammar/Escher.g4 b/src/main/kotlin/tilings/language/grammar/Escher.g4 similarity index 100% rename from src/tilings/language/grammar/Escher.g4 rename to src/main/kotlin/tilings/language/grammar/Escher.g4 diff --git a/src/tilings/language/grammar/Escher.interp b/src/main/kotlin/tilings/language/grammar/Escher.interp similarity index 100% rename from src/tilings/language/grammar/Escher.interp rename to src/main/kotlin/tilings/language/grammar/Escher.interp diff --git a/src/tilings/language/grammar/Escher.tokens b/src/main/kotlin/tilings/language/grammar/Escher.tokens similarity index 100% rename from src/tilings/language/grammar/Escher.tokens rename to src/main/kotlin/tilings/language/grammar/Escher.tokens diff --git a/src/tilings/language/grammar/EscherBaseListener.java b/src/main/kotlin/tilings/language/grammar/EscherBaseListener.java similarity index 100% rename from src/tilings/language/grammar/EscherBaseListener.java rename to src/main/kotlin/tilings/language/grammar/EscherBaseListener.java diff --git a/src/tilings/language/grammar/EscherBaseVisitor.java b/src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java similarity index 100% rename from src/tilings/language/grammar/EscherBaseVisitor.java rename to src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java diff --git a/src/tilings/language/grammar/EscherLexer.interp b/src/main/kotlin/tilings/language/grammar/EscherLexer.interp similarity index 100% rename from src/tilings/language/grammar/EscherLexer.interp rename to src/main/kotlin/tilings/language/grammar/EscherLexer.interp diff --git a/src/tilings/language/grammar/EscherLexer.java b/src/main/kotlin/tilings/language/grammar/EscherLexer.java similarity index 100% rename from src/tilings/language/grammar/EscherLexer.java rename to src/main/kotlin/tilings/language/grammar/EscherLexer.java diff --git a/src/tilings/language/grammar/EscherLexer.tokens b/src/main/kotlin/tilings/language/grammar/EscherLexer.tokens similarity index 100% rename from src/tilings/language/grammar/EscherLexer.tokens rename to src/main/kotlin/tilings/language/grammar/EscherLexer.tokens diff --git a/src/tilings/language/grammar/EscherListener.java b/src/main/kotlin/tilings/language/grammar/EscherListener.java similarity index 100% rename from src/tilings/language/grammar/EscherListener.java rename to src/main/kotlin/tilings/language/grammar/EscherListener.java diff --git a/src/tilings/language/grammar/EscherParser.java b/src/main/kotlin/tilings/language/grammar/EscherParser.java similarity index 100% rename from src/tilings/language/grammar/EscherParser.java rename to src/main/kotlin/tilings/language/grammar/EscherParser.java diff --git a/src/tilings/language/grammar/EscherVisitor.java b/src/main/kotlin/tilings/language/grammar/EscherVisitor.java similarity index 100% rename from src/tilings/language/grammar/EscherVisitor.java rename to src/main/kotlin/tilings/language/grammar/EscherVisitor.java From 5f93e6b21f9b6444742e5e072adff02f41770ae7 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Tue, 26 Jun 2018 18:58:31 -0400 Subject: [PATCH 12/24] restructure so antlr source files are generated with gradle during build --- build.gradle | 6 +- .../tilings/language/grammar/Escher.g4 | 4 + .../tilings/language/grammar/Escher.interp | 80 - .../tilings/language/grammar/Escher.tokens | 45 - .../language/grammar/EscherBaseListener.java | 292 ---- .../language/grammar/EscherBaseVisitor.java | 162 -- .../language/grammar/EscherLexer.interp | 91 - .../tilings/language/grammar/EscherLexer.java | 167 -- .../language/grammar/EscherLexer.tokens | 45 - .../language/grammar/EscherListener.java | 221 --- .../language/grammar/EscherParser.java | 1526 ----------------- .../language/grammar/EscherVisitor.java | 140 -- 12 files changed, 9 insertions(+), 2770 deletions(-) rename src/main/{kotlin => antlr}/tilings/language/grammar/Escher.g4 (97%) delete mode 100644 src/main/kotlin/tilings/language/grammar/Escher.interp delete mode 100644 src/main/kotlin/tilings/language/grammar/Escher.tokens delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherBaseListener.java delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherLexer.interp delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherLexer.java delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherLexer.tokens delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherListener.java delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherParser.java delete mode 100644 src/main/kotlin/tilings/language/grammar/EscherVisitor.java diff --git a/build.gradle b/build.gradle index 4eae9c2..45242b5 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'com.google.osdetector' version '1.4.0' id 'org.jetbrains.kotlin.jvm' version '1.2.10' id 'application' + id 'antlr' } // Set the main class for application and jar building @@ -20,7 +21,6 @@ dependencies { // KoebeLib dependencies compile files('lib/jar/cpcore.jar') - compile 'org.antlr:antlr4:4.7.1' compile 'org.python:jython-standalone:2.7.0' compile 'com.fifesoft:rsyntaxtextarea:2.6.1' compile 'org.jogamp.jogl:jogl-all-main:2.3.2' @@ -28,6 +28,9 @@ dependencies { compile ('org.processing:core:3.3.6') { transitive = false } + + // Antlr dependency + antlr 'org.antlr:antlr4:4.7.1' } task chkLib { @@ -75,6 +78,7 @@ get_win.onlyIf { !cpcore.exists() } // Can't compile without cpcore.jar compileKotlin.dependsOn(get) +compileKotlin.dependsOn(generateGrammarSource) // Build jar with main class defined earlier // Bundle all dependencies in the jar diff --git a/src/main/kotlin/tilings/language/grammar/Escher.g4 b/src/main/antlr/tilings/language/grammar/Escher.g4 similarity index 97% rename from src/main/kotlin/tilings/language/grammar/Escher.g4 rename to src/main/antlr/tilings/language/grammar/Escher.g4 index c656652..a7d16a8 100644 --- a/src/main/kotlin/tilings/language/grammar/Escher.g4 +++ b/src/main/antlr/tilings/language/grammar/Escher.g4 @@ -1,5 +1,9 @@ grammar Escher ; +@header { + package tilings.language.grammar; +} + /* * Parser Rules */ diff --git a/src/main/kotlin/tilings/language/grammar/Escher.interp b/src/main/kotlin/tilings/language/grammar/Escher.interp deleted file mode 100644 index 2d68256..0000000 --- a/src/main/kotlin/tilings/language/grammar/Escher.interp +++ /dev/null @@ -1,80 +0,0 @@ -token literal names: -null -'{' -',' -'}' -'(' -')' -'=' -'[' -']' -'.' -'vertex' -'face' -'GRAPH' -'CHILD' -'SUBDIVISION' -'TILETYPE' -'VERTEX' -'EDGE' -'tile' -'split' -'connect' -';' -null -null -null - -token symbolic names: -null -null -null -null -null -null -null -null -null -null -null -null -GRAPH -CHILD -SUBDIVISION -TILETYPE -VERTEX -EDGE -TILE -SPLIT -CONNECT -END -WHITESPACE -NUMBER -ID - -rule names: -file -mainline -subline -phrase -definition -tileDefinition -subdivisionDefinition -expression -function -tileFunction -splitFunction -connectFunction -assignment -vertexAssignment -edgeAssignment -childAssignment -graphAssignment -graphDeclaration -childList -node -face - - -atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 26, 198, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 3, 2, 6, 2, 46, 10, 2, 13, 2, 14, 2, 47, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 5, 5, 58, 10, 5, 3, 6, 3, 6, 5, 6, 62, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 70, 10, 7, 12, 7, 14, 7, 73, 11, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 6, 8, 81, 10, 8, 13, 8, 14, 8, 82, 3, 8, 3, 8, 3, 9, 3, 9, 5, 9, 89, 10, 9, 3, 10, 3, 10, 3, 10, 5, 10, 94, 10, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 5, 14, 122, 10, 14, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 128, 10, 15, 12, 15, 14, 15, 131, 11, 15, 3, 15, 3, 15, 3, 15, 5, 15, 136, 10, 15, 5, 15, 138, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 150, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 6, 17, 158, 10, 17, 13, 17, 14, 17, 159, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 175, 10, 20, 12, 20, 14, 20, 178, 11, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 188, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 196, 10, 22, 3, 22, 2, 2, 23, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 2, 2, 2, 194, 2, 45, 3, 2, 2, 2, 4, 49, 3, 2, 2, 2, 6, 52, 3, 2, 2, 2, 8, 57, 3, 2, 2, 2, 10, 61, 3, 2, 2, 2, 12, 63, 3, 2, 2, 2, 14, 76, 3, 2, 2, 2, 16, 88, 3, 2, 2, 2, 18, 93, 3, 2, 2, 2, 20, 95, 3, 2, 2, 2, 22, 102, 3, 2, 2, 2, 24, 111, 3, 2, 2, 2, 26, 121, 3, 2, 2, 2, 28, 123, 3, 2, 2, 2, 30, 139, 3, 2, 2, 2, 32, 151, 3, 2, 2, 2, 34, 163, 3, 2, 2, 2, 36, 168, 3, 2, 2, 2, 38, 170, 3, 2, 2, 2, 40, 181, 3, 2, 2, 2, 42, 189, 3, 2, 2, 2, 44, 46, 5, 4, 3, 2, 45, 44, 3, 2, 2, 2, 46, 47, 3, 2, 2, 2, 47, 45, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 3, 3, 2, 2, 2, 49, 50, 5, 8, 5, 2, 50, 51, 7, 23, 2, 2, 51, 5, 3, 2, 2, 2, 52, 53, 5, 16, 9, 2, 53, 54, 7, 23, 2, 2, 54, 7, 3, 2, 2, 2, 55, 58, 5, 10, 6, 2, 56, 58, 5, 16, 9, 2, 57, 55, 3, 2, 2, 2, 57, 56, 3, 2, 2, 2, 58, 9, 3, 2, 2, 2, 59, 62, 5, 12, 7, 2, 60, 62, 5, 14, 8, 2, 61, 59, 3, 2, 2, 2, 61, 60, 3, 2, 2, 2, 62, 11, 3, 2, 2, 2, 63, 64, 7, 17, 2, 2, 64, 65, 7, 26, 2, 2, 65, 66, 7, 3, 2, 2, 66, 71, 7, 25, 2, 2, 67, 68, 7, 4, 2, 2, 68, 70, 7, 25, 2, 2, 69, 67, 3, 2, 2, 2, 70, 73, 3, 2, 2, 2, 71, 69, 3, 2, 2, 2, 71, 72, 3, 2, 2, 2, 72, 74, 3, 2, 2, 2, 73, 71, 3, 2, 2, 2, 74, 75, 7, 5, 2, 2, 75, 13, 3, 2, 2, 2, 76, 77, 7, 16, 2, 2, 77, 78, 7, 26, 2, 2, 78, 80, 7, 3, 2, 2, 79, 81, 5, 6, 4, 2, 80, 79, 3, 2, 2, 2, 81, 82, 3, 2, 2, 2, 82, 80, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 85, 7, 5, 2, 2, 85, 15, 3, 2, 2, 2, 86, 89, 5, 18, 10, 2, 87, 89, 5, 26, 14, 2, 88, 86, 3, 2, 2, 2, 88, 87, 3, 2, 2, 2, 89, 17, 3, 2, 2, 2, 90, 94, 5, 20, 11, 2, 91, 94, 5, 22, 12, 2, 92, 94, 5, 24, 13, 2, 93, 90, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 92, 3, 2, 2, 2, 94, 19, 3, 2, 2, 2, 95, 96, 7, 20, 2, 2, 96, 97, 7, 6, 2, 2, 97, 98, 7, 26, 2, 2, 98, 99, 7, 4, 2, 2, 99, 100, 7, 25, 2, 2, 100, 101, 7, 7, 2, 2, 101, 21, 3, 2, 2, 2, 102, 103, 7, 21, 2, 2, 103, 104, 7, 6, 2, 2, 104, 105, 5, 40, 21, 2, 105, 106, 7, 4, 2, 2, 106, 107, 5, 40, 21, 2, 107, 108, 7, 4, 2, 2, 108, 109, 7, 25, 2, 2, 109, 110, 7, 7, 2, 2, 110, 23, 3, 2, 2, 2, 111, 112, 7, 22, 2, 2, 112, 113, 7, 6, 2, 2, 113, 114, 5, 40, 21, 2, 114, 115, 7, 4, 2, 2, 115, 116, 5, 40, 21, 2, 116, 117, 7, 7, 2, 2, 117, 25, 3, 2, 2, 2, 118, 122, 5, 28, 15, 2, 119, 122, 5, 30, 16, 2, 120, 122, 5, 32, 17, 2, 121, 118, 3, 2, 2, 2, 121, 119, 3, 2, 2, 2, 121, 120, 3, 2, 2, 2, 122, 27, 3, 2, 2, 2, 123, 124, 7, 18, 2, 2, 124, 129, 7, 26, 2, 2, 125, 126, 7, 4, 2, 2, 126, 128, 7, 26, 2, 2, 127, 125, 3, 2, 2, 2, 128, 131, 3, 2, 2, 2, 129, 127, 3, 2, 2, 2, 129, 130, 3, 2, 2, 2, 130, 137, 3, 2, 2, 2, 131, 129, 3, 2, 2, 2, 132, 135, 7, 8, 2, 2, 133, 136, 5, 22, 12, 2, 134, 136, 5, 40, 21, 2, 135, 133, 3, 2, 2, 2, 135, 134, 3, 2, 2, 2, 136, 138, 3, 2, 2, 2, 137, 132, 3, 2, 2, 2, 137, 138, 3, 2, 2, 2, 138, 29, 3, 2, 2, 2, 139, 140, 7, 19, 2, 2, 140, 149, 7, 26, 2, 2, 141, 142, 7, 8, 2, 2, 142, 150, 5, 24, 13, 2, 143, 144, 7, 6, 2, 2, 144, 145, 5, 40, 21, 2, 145, 146, 7, 4, 2, 2, 146, 147, 5, 40, 21, 2, 147, 148, 7, 7, 2, 2, 148, 150, 3, 2, 2, 2, 149, 141, 3, 2, 2, 2, 149, 143, 3, 2, 2, 2, 150, 31, 3, 2, 2, 2, 151, 152, 7, 15, 2, 2, 152, 153, 7, 26, 2, 2, 153, 154, 7, 8, 2, 2, 154, 155, 7, 26, 2, 2, 155, 157, 7, 6, 2, 2, 156, 158, 5, 38, 20, 2, 157, 156, 3, 2, 2, 2, 158, 159, 3, 2, 2, 2, 159, 157, 3, 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 161, 3, 2, 2, 2, 161, 162, 7, 7, 2, 2, 162, 33, 3, 2, 2, 2, 163, 164, 7, 14, 2, 2, 164, 165, 7, 26, 2, 2, 165, 166, 7, 8, 2, 2, 166, 167, 5, 36, 19, 2, 167, 35, 3, 2, 2, 2, 168, 169, 5, 20, 11, 2, 169, 37, 3, 2, 2, 2, 170, 171, 7, 9, 2, 2, 171, 176, 5, 40, 21, 2, 172, 173, 7, 4, 2, 2, 173, 175, 5, 40, 21, 2, 174, 172, 3, 2, 2, 2, 175, 178, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 179, 3, 2, 2, 2, 178, 176, 3, 2, 2, 2, 179, 180, 7, 10, 2, 2, 180, 39, 3, 2, 2, 2, 181, 187, 7, 26, 2, 2, 182, 183, 7, 11, 2, 2, 183, 184, 7, 12, 2, 2, 184, 185, 7, 9, 2, 2, 185, 186, 7, 25, 2, 2, 186, 188, 7, 10, 2, 2, 187, 182, 3, 2, 2, 2, 187, 188, 3, 2, 2, 2, 188, 41, 3, 2, 2, 2, 189, 195, 7, 26, 2, 2, 190, 191, 7, 11, 2, 2, 191, 192, 7, 13, 2, 2, 192, 193, 7, 9, 2, 2, 193, 194, 7, 25, 2, 2, 194, 196, 7, 10, 2, 2, 195, 190, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 43, 3, 2, 2, 2, 18, 47, 57, 61, 71, 82, 88, 93, 121, 129, 135, 137, 149, 159, 176, 187, 195] \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/Escher.tokens b/src/main/kotlin/tilings/language/grammar/Escher.tokens deleted file mode 100644 index 658598d..0000000 --- a/src/main/kotlin/tilings/language/grammar/Escher.tokens +++ /dev/null @@ -1,45 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -T__8=9 -T__9=10 -T__10=11 -GRAPH=12 -CHILD=13 -SUBDIVISION=14 -TILETYPE=15 -VERTEX=16 -EDGE=17 -TILE=18 -SPLIT=19 -CONNECT=20 -END=21 -WHITESPACE=22 -NUMBER=23 -ID=24 -'{'=1 -','=2 -'}'=3 -'('=4 -')'=5 -'='=6 -'['=7 -']'=8 -'.'=9 -'vertex'=10 -'face'=11 -'GRAPH'=12 -'CHILD'=13 -'SUBDIVISION'=14 -'TILETYPE'=15 -'VERTEX'=16 -'EDGE'=17 -'tile'=18 -'split'=19 -'connect'=20 -';'=21 diff --git a/src/main/kotlin/tilings/language/grammar/EscherBaseListener.java b/src/main/kotlin/tilings/language/grammar/EscherBaseListener.java deleted file mode 100644 index d052dc4..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherBaseListener.java +++ /dev/null @@ -1,292 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 - -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.tree.ErrorNode; -import org.antlr.v4.runtime.tree.TerminalNode; - -/** - * This class provides an empty implementation of {@link EscherListener}, - * which can be extended to create a listener which only needs to handle a subset - * of the available methods. - */ -public class EscherBaseListener implements EscherListener { - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterFile(EscherParser.FileContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitFile(EscherParser.FileContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterMainline(EscherParser.MainlineContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitMainline(EscherParser.MainlineContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterSubline(EscherParser.SublineContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitSubline(EscherParser.SublineContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterPhrase(EscherParser.PhraseContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitPhrase(EscherParser.PhraseContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterDefinition(EscherParser.DefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitDefinition(EscherParser.DefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterTileDefinition(EscherParser.TileDefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitTileDefinition(EscherParser.TileDefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterExpression(EscherParser.ExpressionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitExpression(EscherParser.ExpressionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterFunction(EscherParser.FunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitFunction(EscherParser.FunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterTileFunction(EscherParser.TileFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitTileFunction(EscherParser.TileFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterSplitFunction(EscherParser.SplitFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitSplitFunction(EscherParser.SplitFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterConnectFunction(EscherParser.ConnectFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitConnectFunction(EscherParser.ConnectFunctionContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterAssignment(EscherParser.AssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitAssignment(EscherParser.AssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterVertexAssignment(EscherParser.VertexAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitVertexAssignment(EscherParser.VertexAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterEdgeAssignment(EscherParser.EdgeAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitEdgeAssignment(EscherParser.EdgeAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterChildAssignment(EscherParser.ChildAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitChildAssignment(EscherParser.ChildAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterGraphAssignment(EscherParser.GraphAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitGraphAssignment(EscherParser.GraphAssignmentContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterGraphDeclaration(EscherParser.GraphDeclarationContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitGraphDeclaration(EscherParser.GraphDeclarationContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterChildList(EscherParser.ChildListContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitChildList(EscherParser.ChildListContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterNode(EscherParser.NodeContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitNode(EscherParser.NodeContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterFace(EscherParser.FaceContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitFace(EscherParser.FaceContext ctx) { } - - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterEveryRule(ParserRuleContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitEveryRule(ParserRuleContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void visitTerminal(TerminalNode node) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void visitErrorNode(ErrorNode node) { } -} \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java b/src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java deleted file mode 100644 index 4c62a94..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherBaseVisitor.java +++ /dev/null @@ -1,162 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 -import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; - -/** - * This class provides an empty implementation of {@link EscherVisitor}, - * which can be extended to create a visitor which only needs to handle a subset - * of the available methods. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -public class EscherBaseVisitor extends AbstractParseTreeVisitor implements EscherVisitor { - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFile(EscherParser.FileContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitMainline(EscherParser.MainlineContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSubline(EscherParser.SublineContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitPhrase(EscherParser.PhraseContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitDefinition(EscherParser.DefinitionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTileDefinition(EscherParser.TileDefinitionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitExpression(EscherParser.ExpressionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFunction(EscherParser.FunctionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTileFunction(EscherParser.TileFunctionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSplitFunction(EscherParser.SplitFunctionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitConnectFunction(EscherParser.ConnectFunctionContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitAssignment(EscherParser.AssignmentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitVertexAssignment(EscherParser.VertexAssignmentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitEdgeAssignment(EscherParser.EdgeAssignmentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitChildAssignment(EscherParser.ChildAssignmentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitGraphAssignment(EscherParser.GraphAssignmentContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitGraphDeclaration(EscherParser.GraphDeclarationContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitChildList(EscherParser.ChildListContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitNode(EscherParser.NodeContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFace(EscherParser.FaceContext ctx) { return visitChildren(ctx); } -} \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherLexer.interp b/src/main/kotlin/tilings/language/grammar/EscherLexer.interp deleted file mode 100644 index dcc774b..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherLexer.interp +++ /dev/null @@ -1,91 +0,0 @@ -token literal names: -null -'{' -',' -'}' -'(' -')' -'=' -'[' -']' -'.' -'vertex' -'face' -'GRAPH' -'CHILD' -'SUBDIVISION' -'TILETYPE' -'VERTEX' -'EDGE' -'tile' -'split' -'connect' -';' -null -null -null - -token symbolic names: -null -null -null -null -null -null -null -null -null -null -null -null -GRAPH -CHILD -SUBDIVISION -TILETYPE -VERTEX -EDGE -TILE -SPLIT -CONNECT -END -WHITESPACE -NUMBER -ID - -rule names: -T__0 -T__1 -T__2 -T__3 -T__4 -T__5 -T__6 -T__7 -T__8 -T__9 -T__10 -LETTER -DIGIT -GRAPH -CHILD -SUBDIVISION -TILETYPE -VERTEX -EDGE -TILE -SPLIT -CONNECT -END -WHITESPACE -NUMBER -ID - -channel names: -DEFAULT_TOKEN_CHANNEL -HIDDEN - -mode names: -DEFAULT_MODE - -atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 26, 178, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 6, 13, 87, 10, 13, 13, 13, 14, 13, 88, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 6, 25, 160, 10, 25, 13, 25, 14, 25, 161, 3, 25, 3, 25, 3, 26, 6, 26, 167, 10, 26, 13, 26, 14, 26, 168, 3, 27, 3, 27, 3, 27, 7, 27, 174, 10, 27, 12, 27, 14, 27, 177, 11, 27, 2, 2, 28, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 2, 27, 2, 29, 14, 31, 15, 33, 16, 35, 17, 37, 18, 39, 19, 41, 20, 43, 21, 45, 22, 47, 23, 49, 24, 51, 25, 53, 26, 3, 2, 4, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 2, 180, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 5, 57, 3, 2, 2, 2, 7, 59, 3, 2, 2, 2, 9, 61, 3, 2, 2, 2, 11, 63, 3, 2, 2, 2, 13, 65, 3, 2, 2, 2, 15, 67, 3, 2, 2, 2, 17, 69, 3, 2, 2, 2, 19, 71, 3, 2, 2, 2, 21, 73, 3, 2, 2, 2, 23, 80, 3, 2, 2, 2, 25, 86, 3, 2, 2, 2, 27, 90, 3, 2, 2, 2, 29, 92, 3, 2, 2, 2, 31, 98, 3, 2, 2, 2, 33, 104, 3, 2, 2, 2, 35, 116, 3, 2, 2, 2, 37, 125, 3, 2, 2, 2, 39, 132, 3, 2, 2, 2, 41, 137, 3, 2, 2, 2, 43, 142, 3, 2, 2, 2, 45, 148, 3, 2, 2, 2, 47, 156, 3, 2, 2, 2, 49, 159, 3, 2, 2, 2, 51, 166, 3, 2, 2, 2, 53, 170, 3, 2, 2, 2, 55, 56, 7, 125, 2, 2, 56, 4, 3, 2, 2, 2, 57, 58, 7, 46, 2, 2, 58, 6, 3, 2, 2, 2, 59, 60, 7, 127, 2, 2, 60, 8, 3, 2, 2, 2, 61, 62, 7, 42, 2, 2, 62, 10, 3, 2, 2, 2, 63, 64, 7, 43, 2, 2, 64, 12, 3, 2, 2, 2, 65, 66, 7, 63, 2, 2, 66, 14, 3, 2, 2, 2, 67, 68, 7, 93, 2, 2, 68, 16, 3, 2, 2, 2, 69, 70, 7, 95, 2, 2, 70, 18, 3, 2, 2, 2, 71, 72, 7, 48, 2, 2, 72, 20, 3, 2, 2, 2, 73, 74, 7, 120, 2, 2, 74, 75, 7, 103, 2, 2, 75, 76, 7, 116, 2, 2, 76, 77, 7, 118, 2, 2, 77, 78, 7, 103, 2, 2, 78, 79, 7, 122, 2, 2, 79, 22, 3, 2, 2, 2, 80, 81, 7, 104, 2, 2, 81, 82, 7, 99, 2, 2, 82, 83, 7, 101, 2, 2, 83, 84, 7, 103, 2, 2, 84, 24, 3, 2, 2, 2, 85, 87, 9, 2, 2, 2, 86, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 86, 3, 2, 2, 2, 88, 89, 3, 2, 2, 2, 89, 26, 3, 2, 2, 2, 90, 91, 4, 50, 59, 2, 91, 28, 3, 2, 2, 2, 92, 93, 7, 73, 2, 2, 93, 94, 7, 84, 2, 2, 94, 95, 7, 67, 2, 2, 95, 96, 7, 82, 2, 2, 96, 97, 7, 74, 2, 2, 97, 30, 3, 2, 2, 2, 98, 99, 7, 69, 2, 2, 99, 100, 7, 74, 2, 2, 100, 101, 7, 75, 2, 2, 101, 102, 7, 78, 2, 2, 102, 103, 7, 70, 2, 2, 103, 32, 3, 2, 2, 2, 104, 105, 7, 85, 2, 2, 105, 106, 7, 87, 2, 2, 106, 107, 7, 68, 2, 2, 107, 108, 7, 70, 2, 2, 108, 109, 7, 75, 2, 2, 109, 110, 7, 88, 2, 2, 110, 111, 7, 75, 2, 2, 111, 112, 7, 85, 2, 2, 112, 113, 7, 75, 2, 2, 113, 114, 7, 81, 2, 2, 114, 115, 7, 80, 2, 2, 115, 34, 3, 2, 2, 2, 116, 117, 7, 86, 2, 2, 117, 118, 7, 75, 2, 2, 118, 119, 7, 78, 2, 2, 119, 120, 7, 71, 2, 2, 120, 121, 7, 86, 2, 2, 121, 122, 7, 91, 2, 2, 122, 123, 7, 82, 2, 2, 123, 124, 7, 71, 2, 2, 124, 36, 3, 2, 2, 2, 125, 126, 7, 88, 2, 2, 126, 127, 7, 71, 2, 2, 127, 128, 7, 84, 2, 2, 128, 129, 7, 86, 2, 2, 129, 130, 7, 71, 2, 2, 130, 131, 7, 90, 2, 2, 131, 38, 3, 2, 2, 2, 132, 133, 7, 71, 2, 2, 133, 134, 7, 70, 2, 2, 134, 135, 7, 73, 2, 2, 135, 136, 7, 71, 2, 2, 136, 40, 3, 2, 2, 2, 137, 138, 7, 118, 2, 2, 138, 139, 7, 107, 2, 2, 139, 140, 7, 110, 2, 2, 140, 141, 7, 103, 2, 2, 141, 42, 3, 2, 2, 2, 142, 143, 7, 117, 2, 2, 143, 144, 7, 114, 2, 2, 144, 145, 7, 110, 2, 2, 145, 146, 7, 107, 2, 2, 146, 147, 7, 118, 2, 2, 147, 44, 3, 2, 2, 2, 148, 149, 7, 101, 2, 2, 149, 150, 7, 113, 2, 2, 150, 151, 7, 112, 2, 2, 151, 152, 7, 112, 2, 2, 152, 153, 7, 103, 2, 2, 153, 154, 7, 101, 2, 2, 154, 155, 7, 118, 2, 2, 155, 46, 3, 2, 2, 2, 156, 157, 7, 61, 2, 2, 157, 48, 3, 2, 2, 2, 158, 160, 9, 3, 2, 2, 159, 158, 3, 2, 2, 2, 160, 161, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 163, 3, 2, 2, 2, 163, 164, 8, 25, 2, 2, 164, 50, 3, 2, 2, 2, 165, 167, 5, 27, 14, 2, 166, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 168, 169, 3, 2, 2, 2, 169, 52, 3, 2, 2, 2, 170, 175, 5, 25, 13, 2, 171, 174, 5, 25, 13, 2, 172, 174, 5, 27, 14, 2, 173, 171, 3, 2, 2, 2, 173, 172, 3, 2, 2, 2, 174, 177, 3, 2, 2, 2, 175, 173, 3, 2, 2, 2, 175, 176, 3, 2, 2, 2, 176, 54, 3, 2, 2, 2, 177, 175, 3, 2, 2, 2, 8, 2, 88, 161, 168, 173, 175, 3, 8, 2, 2] \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherLexer.java b/src/main/kotlin/tilings/language/grammar/EscherLexer.java deleted file mode 100644 index e3e481e..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherLexer.java +++ /dev/null @@ -1,167 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) -public class EscherLexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, T__10=11, GRAPH=12, CHILD=13, SUBDIVISION=14, TILETYPE=15, VERTEX=16, - EDGE=17, TILE=18, SPLIT=19, CONNECT=20, END=21, WHITESPACE=22, NUMBER=23, - ID=24; - public static String[] channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" - }; - - public static String[] modeNames = { - "DEFAULT_MODE" - }; - - public static final String[] ruleNames = { - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", - "T__9", "T__10", "LETTER", "DIGIT", "GRAPH", "CHILD", "SUBDIVISION", "TILETYPE", - "VERTEX", "EDGE", "TILE", "SPLIT", "CONNECT", "END", "WHITESPACE", "NUMBER", - "ID" - }; - - private static final String[] _LITERAL_NAMES = { - null, "'{'", "','", "'}'", "'('", "')'", "'='", "'['", "']'", "'.'", "'vertex'", - "'face'", "'GRAPH'", "'CHILD'", "'SUBDIVISION'", "'TILETYPE'", "'VERTEX'", - "'EDGE'", "'tile'", "'split'", "'connect'", "';'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, null, - "GRAPH", "CHILD", "SUBDIVISION", "TILETYPE", "VERTEX", "EDGE", "TILE", - "SPLIT", "CONNECT", "END", "WHITESPACE", "NUMBER", "ID" - }; - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - - public EscherLexer(CharStream input) { - super(input); - _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @Override - public String getGrammarFileName() { return "Escher.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public String[] getChannelNames() { return channelNames; } - - @Override - public String[] getModeNames() { return modeNames; } - - @Override - public ATN getATN() { return _ATN; } - - public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\32\u00b2\b\1\4\2"+ - "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ - "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ - "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ - "\t\31\4\32\t\32\4\33\t\33\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7"+ - "\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3"+ - "\f\3\f\3\f\3\f\3\r\6\rW\n\r\r\r\16\rX\3\16\3\16\3\17\3\17\3\17\3\17\3"+ - "\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3"+ - "\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3"+ - "\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\25\3"+ - "\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3"+ - "\27\3\27\3\27\3\27\3\30\3\30\3\31\6\31\u00a0\n\31\r\31\16\31\u00a1\3\31"+ - "\3\31\3\32\6\32\u00a7\n\32\r\32\16\32\u00a8\3\33\3\33\3\33\7\33\u00ae"+ - "\n\33\f\33\16\33\u00b1\13\33\2\2\34\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n"+ - "\23\13\25\f\27\r\31\2\33\2\35\16\37\17!\20#\21%\22\'\23)\24+\25-\26/\27"+ - "\61\30\63\31\65\32\3\2\4\4\2C\\c|\5\2\13\f\17\17\"\"\2\u00b4\2\3\3\2\2"+ - "\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3"+ - "\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\35\3\2\2"+ - "\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2"+ - "\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2"+ - "\2\2\3\67\3\2\2\2\59\3\2\2\2\7;\3\2\2\2\t=\3\2\2\2\13?\3\2\2\2\rA\3\2"+ - "\2\2\17C\3\2\2\2\21E\3\2\2\2\23G\3\2\2\2\25I\3\2\2\2\27P\3\2\2\2\31V\3"+ - "\2\2\2\33Z\3\2\2\2\35\\\3\2\2\2\37b\3\2\2\2!h\3\2\2\2#t\3\2\2\2%}\3\2"+ - "\2\2\'\u0084\3\2\2\2)\u0089\3\2\2\2+\u008e\3\2\2\2-\u0094\3\2\2\2/\u009c"+ - "\3\2\2\2\61\u009f\3\2\2\2\63\u00a6\3\2\2\2\65\u00aa\3\2\2\2\678\7}\2\2"+ - "8\4\3\2\2\29:\7.\2\2:\6\3\2\2\2;<\7\177\2\2<\b\3\2\2\2=>\7*\2\2>\n\3\2"+ - "\2\2?@\7+\2\2@\f\3\2\2\2AB\7?\2\2B\16\3\2\2\2CD\7]\2\2D\20\3\2\2\2EF\7"+ - "_\2\2F\22\3\2\2\2GH\7\60\2\2H\24\3\2\2\2IJ\7x\2\2JK\7g\2\2KL\7t\2\2LM"+ - "\7v\2\2MN\7g\2\2NO\7z\2\2O\26\3\2\2\2PQ\7h\2\2QR\7c\2\2RS\7e\2\2ST\7g"+ - "\2\2T\30\3\2\2\2UW\t\2\2\2VU\3\2\2\2WX\3\2\2\2XV\3\2\2\2XY\3\2\2\2Y\32"+ - "\3\2\2\2Z[\4\62;\2[\34\3\2\2\2\\]\7I\2\2]^\7T\2\2^_\7C\2\2_`\7R\2\2`a"+ - "\7J\2\2a\36\3\2\2\2bc\7E\2\2cd\7J\2\2de\7K\2\2ef\7N\2\2fg\7F\2\2g \3\2"+ - "\2\2hi\7U\2\2ij\7W\2\2jk\7D\2\2kl\7F\2\2lm\7K\2\2mn\7X\2\2no\7K\2\2op"+ - "\7U\2\2pq\7K\2\2qr\7Q\2\2rs\7P\2\2s\"\3\2\2\2tu\7V\2\2uv\7K\2\2vw\7N\2"+ - "\2wx\7G\2\2xy\7V\2\2yz\7[\2\2z{\7R\2\2{|\7G\2\2|$\3\2\2\2}~\7X\2\2~\177"+ - "\7G\2\2\177\u0080\7T\2\2\u0080\u0081\7V\2\2\u0081\u0082\7G\2\2\u0082\u0083"+ - "\7Z\2\2\u0083&\3\2\2\2\u0084\u0085\7G\2\2\u0085\u0086\7F\2\2\u0086\u0087"+ - "\7I\2\2\u0087\u0088\7G\2\2\u0088(\3\2\2\2\u0089\u008a\7v\2\2\u008a\u008b"+ - "\7k\2\2\u008b\u008c\7n\2\2\u008c\u008d\7g\2\2\u008d*\3\2\2\2\u008e\u008f"+ - "\7u\2\2\u008f\u0090\7r\2\2\u0090\u0091\7n\2\2\u0091\u0092\7k\2\2\u0092"+ - "\u0093\7v\2\2\u0093,\3\2\2\2\u0094\u0095\7e\2\2\u0095\u0096\7q\2\2\u0096"+ - "\u0097\7p\2\2\u0097\u0098\7p\2\2\u0098\u0099\7g\2\2\u0099\u009a\7e\2\2"+ - "\u009a\u009b\7v\2\2\u009b.\3\2\2\2\u009c\u009d\7=\2\2\u009d\60\3\2\2\2"+ - "\u009e\u00a0\t\3\2\2\u009f\u009e\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\u009f"+ - "\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3\u00a4\b\31\2\2"+ - "\u00a4\62\3\2\2\2\u00a5\u00a7\5\33\16\2\u00a6\u00a5\3\2\2\2\u00a7\u00a8"+ - "\3\2\2\2\u00a8\u00a6\3\2\2\2\u00a8\u00a9\3\2\2\2\u00a9\64\3\2\2\2\u00aa"+ - "\u00af\5\31\r\2\u00ab\u00ae\5\31\r\2\u00ac\u00ae\5\33\16\2\u00ad\u00ab"+ - "\3\2\2\2\u00ad\u00ac\3\2\2\2\u00ae\u00b1\3\2\2\2\u00af\u00ad\3\2\2\2\u00af"+ - "\u00b0\3\2\2\2\u00b0\66\3\2\2\2\u00b1\u00af\3\2\2\2\b\2X\u00a1\u00a8\u00ad"+ - "\u00af\3\b\2\2"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherLexer.tokens b/src/main/kotlin/tilings/language/grammar/EscherLexer.tokens deleted file mode 100644 index 658598d..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherLexer.tokens +++ /dev/null @@ -1,45 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -T__8=9 -T__9=10 -T__10=11 -GRAPH=12 -CHILD=13 -SUBDIVISION=14 -TILETYPE=15 -VERTEX=16 -EDGE=17 -TILE=18 -SPLIT=19 -CONNECT=20 -END=21 -WHITESPACE=22 -NUMBER=23 -ID=24 -'{'=1 -','=2 -'}'=3 -'('=4 -')'=5 -'='=6 -'['=7 -']'=8 -'.'=9 -'vertex'=10 -'face'=11 -'GRAPH'=12 -'CHILD'=13 -'SUBDIVISION'=14 -'TILETYPE'=15 -'VERTEX'=16 -'EDGE'=17 -'tile'=18 -'split'=19 -'connect'=20 -';'=21 diff --git a/src/main/kotlin/tilings/language/grammar/EscherListener.java b/src/main/kotlin/tilings/language/grammar/EscherListener.java deleted file mode 100644 index 946ebf8..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherListener.java +++ /dev/null @@ -1,221 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 -import org.antlr.v4.runtime.tree.ParseTreeListener; - -/** - * This interface defines a complete listener for a parse tree produced by - * {@link EscherParser}. - */ -public interface EscherListener extends ParseTreeListener { - /** - * Enter a parse tree produced by {@link EscherParser#file}. - * @param ctx the parse tree - */ - void enterFile(EscherParser.FileContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#file}. - * @param ctx the parse tree - */ - void exitFile(EscherParser.FileContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#mainline}. - * @param ctx the parse tree - */ - void enterMainline(EscherParser.MainlineContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#mainline}. - * @param ctx the parse tree - */ - void exitMainline(EscherParser.MainlineContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#subline}. - * @param ctx the parse tree - */ - void enterSubline(EscherParser.SublineContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#subline}. - * @param ctx the parse tree - */ - void exitSubline(EscherParser.SublineContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#phrase}. - * @param ctx the parse tree - */ - void enterPhrase(EscherParser.PhraseContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#phrase}. - * @param ctx the parse tree - */ - void exitPhrase(EscherParser.PhraseContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#definition}. - * @param ctx the parse tree - */ - void enterDefinition(EscherParser.DefinitionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#definition}. - * @param ctx the parse tree - */ - void exitDefinition(EscherParser.DefinitionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#tileDefinition}. - * @param ctx the parse tree - */ - void enterTileDefinition(EscherParser.TileDefinitionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#tileDefinition}. - * @param ctx the parse tree - */ - void exitTileDefinition(EscherParser.TileDefinitionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#subdivisionDefinition}. - * @param ctx the parse tree - */ - void enterSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#subdivisionDefinition}. - * @param ctx the parse tree - */ - void exitSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#expression}. - * @param ctx the parse tree - */ - void enterExpression(EscherParser.ExpressionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#expression}. - * @param ctx the parse tree - */ - void exitExpression(EscherParser.ExpressionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#function}. - * @param ctx the parse tree - */ - void enterFunction(EscherParser.FunctionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#function}. - * @param ctx the parse tree - */ - void exitFunction(EscherParser.FunctionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#tileFunction}. - * @param ctx the parse tree - */ - void enterTileFunction(EscherParser.TileFunctionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#tileFunction}. - * @param ctx the parse tree - */ - void exitTileFunction(EscherParser.TileFunctionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#splitFunction}. - * @param ctx the parse tree - */ - void enterSplitFunction(EscherParser.SplitFunctionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#splitFunction}. - * @param ctx the parse tree - */ - void exitSplitFunction(EscherParser.SplitFunctionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#connectFunction}. - * @param ctx the parse tree - */ - void enterConnectFunction(EscherParser.ConnectFunctionContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#connectFunction}. - * @param ctx the parse tree - */ - void exitConnectFunction(EscherParser.ConnectFunctionContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#assignment}. - * @param ctx the parse tree - */ - void enterAssignment(EscherParser.AssignmentContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#assignment}. - * @param ctx the parse tree - */ - void exitAssignment(EscherParser.AssignmentContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#vertexAssignment}. - * @param ctx the parse tree - */ - void enterVertexAssignment(EscherParser.VertexAssignmentContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#vertexAssignment}. - * @param ctx the parse tree - */ - void exitVertexAssignment(EscherParser.VertexAssignmentContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#edgeAssignment}. - * @param ctx the parse tree - */ - void enterEdgeAssignment(EscherParser.EdgeAssignmentContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#edgeAssignment}. - * @param ctx the parse tree - */ - void exitEdgeAssignment(EscherParser.EdgeAssignmentContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#childAssignment}. - * @param ctx the parse tree - */ - void enterChildAssignment(EscherParser.ChildAssignmentContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#childAssignment}. - * @param ctx the parse tree - */ - void exitChildAssignment(EscherParser.ChildAssignmentContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#graphAssignment}. - * @param ctx the parse tree - */ - void enterGraphAssignment(EscherParser.GraphAssignmentContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#graphAssignment}. - * @param ctx the parse tree - */ - void exitGraphAssignment(EscherParser.GraphAssignmentContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#graphDeclaration}. - * @param ctx the parse tree - */ - void enterGraphDeclaration(EscherParser.GraphDeclarationContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#graphDeclaration}. - * @param ctx the parse tree - */ - void exitGraphDeclaration(EscherParser.GraphDeclarationContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#childList}. - * @param ctx the parse tree - */ - void enterChildList(EscherParser.ChildListContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#childList}. - * @param ctx the parse tree - */ - void exitChildList(EscherParser.ChildListContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#node}. - * @param ctx the parse tree - */ - void enterNode(EscherParser.NodeContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#node}. - * @param ctx the parse tree - */ - void exitNode(EscherParser.NodeContext ctx); - /** - * Enter a parse tree produced by {@link EscherParser#face}. - * @param ctx the parse tree - */ - void enterFace(EscherParser.FaceContext ctx); - /** - * Exit a parse tree produced by {@link EscherParser#face}. - * @param ctx the parse tree - */ - void exitFace(EscherParser.FaceContext ctx); -} \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherParser.java b/src/main/kotlin/tilings/language/grammar/EscherParser.java deleted file mode 100644 index 7328455..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherParser.java +++ /dev/null @@ -1,1526 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.misc.*; -import org.antlr.v4.runtime.tree.*; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) -public class EscherParser extends Parser { - static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, T__10=11, GRAPH=12, CHILD=13, SUBDIVISION=14, TILETYPE=15, VERTEX=16, - EDGE=17, TILE=18, SPLIT=19, CONNECT=20, END=21, WHITESPACE=22, NUMBER=23, - ID=24; - public static final int - RULE_file = 0, RULE_mainline = 1, RULE_subline = 2, RULE_phrase = 3, RULE_definition = 4, - RULE_tileDefinition = 5, RULE_subdivisionDefinition = 6, RULE_expression = 7, - RULE_function = 8, RULE_tileFunction = 9, RULE_splitFunction = 10, RULE_connectFunction = 11, - RULE_assignment = 12, RULE_vertexAssignment = 13, RULE_edgeAssignment = 14, - RULE_childAssignment = 15, RULE_graphAssignment = 16, RULE_graphDeclaration = 17, - RULE_childList = 18, RULE_node = 19, RULE_face = 20; - public static final String[] ruleNames = { - "file", "mainline", "subline", "phrase", "definition", "tileDefinition", - "subdivisionDefinition", "expression", "function", "tileFunction", "splitFunction", - "connectFunction", "assignment", "vertexAssignment", "edgeAssignment", - "childAssignment", "graphAssignment", "graphDeclaration", "childList", - "node", "face" - }; - - private static final String[] _LITERAL_NAMES = { - null, "'{'", "','", "'}'", "'('", "')'", "'='", "'['", "']'", "'.'", "'vertex'", - "'face'", "'GRAPH'", "'CHILD'", "'SUBDIVISION'", "'TILETYPE'", "'VERTEX'", - "'EDGE'", "'tile'", "'split'", "'connect'", "';'" - }; - private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, null, - "GRAPH", "CHILD", "SUBDIVISION", "TILETYPE", "VERTEX", "EDGE", "TILE", - "SPLIT", "CONNECT", "END", "WHITESPACE", "NUMBER", "ID" - }; - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - @Override - public String getGrammarFileName() { return "Escher.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public ATN getATN() { return _ATN; } - - public EscherParser(TokenStream input) { - super(input); - _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - public static class FileContext extends ParserRuleContext { - public List mainline() { - return getRuleContexts(MainlineContext.class); - } - public MainlineContext mainline(int i) { - return getRuleContext(MainlineContext.class,i); - } - public FileContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_file; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterFile(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitFile(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitFile(this); - else return visitor.visitChildren(this); - } - } - - public final FileContext file() throws RecognitionException { - FileContext _localctx = new FileContext(_ctx, getState()); - enterRule(_localctx, 0, RULE_file); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(43); - _errHandler.sync(this); - _la = _input.LA(1); - do { - { - { - setState(42); - mainline(); - } - } - setState(45); - _errHandler.sync(this); - _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << CHILD) | (1L << SUBDIVISION) | (1L << TILETYPE) | (1L << VERTEX) | (1L << EDGE) | (1L << TILE) | (1L << SPLIT) | (1L << CONNECT))) != 0) ); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class MainlineContext extends ParserRuleContext { - public PhraseContext phrase() { - return getRuleContext(PhraseContext.class,0); - } - public TerminalNode END() { return getToken(EscherParser.END, 0); } - public MainlineContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_mainline; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterMainline(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitMainline(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitMainline(this); - else return visitor.visitChildren(this); - } - } - - public final MainlineContext mainline() throws RecognitionException { - MainlineContext _localctx = new MainlineContext(_ctx, getState()); - enterRule(_localctx, 2, RULE_mainline); - try { - enterOuterAlt(_localctx, 1); - { - setState(47); - phrase(); - setState(48); - match(END); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class SublineContext extends ParserRuleContext { - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode END() { return getToken(EscherParser.END, 0); } - public SublineContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subline; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterSubline(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitSubline(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitSubline(this); - else return visitor.visitChildren(this); - } - } - - public final SublineContext subline() throws RecognitionException { - SublineContext _localctx = new SublineContext(_ctx, getState()); - enterRule(_localctx, 4, RULE_subline); - try { - enterOuterAlt(_localctx, 1); - { - setState(50); - expression(); - setState(51); - match(END); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class PhraseContext extends ParserRuleContext { - public DefinitionContext definition() { - return getRuleContext(DefinitionContext.class,0); - } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public PhraseContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_phrase; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterPhrase(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitPhrase(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitPhrase(this); - else return visitor.visitChildren(this); - } - } - - public final PhraseContext phrase() throws RecognitionException { - PhraseContext _localctx = new PhraseContext(_ctx, getState()); - enterRule(_localctx, 6, RULE_phrase); - try { - setState(55); - _errHandler.sync(this); - switch (_input.LA(1)) { - case SUBDIVISION: - case TILETYPE: - enterOuterAlt(_localctx, 1); - { - setState(53); - definition(); - } - break; - case CHILD: - case VERTEX: - case EDGE: - case TILE: - case SPLIT: - case CONNECT: - enterOuterAlt(_localctx, 2); - { - setState(54); - expression(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class DefinitionContext extends ParserRuleContext { - public TileDefinitionContext tileDefinition() { - return getRuleContext(TileDefinitionContext.class,0); - } - public SubdivisionDefinitionContext subdivisionDefinition() { - return getRuleContext(SubdivisionDefinitionContext.class,0); - } - public DefinitionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_definition; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterDefinition(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitDefinition(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitDefinition(this); - else return visitor.visitChildren(this); - } - } - - public final DefinitionContext definition() throws RecognitionException { - DefinitionContext _localctx = new DefinitionContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_definition); - try { - setState(59); - _errHandler.sync(this); - switch (_input.LA(1)) { - case TILETYPE: - enterOuterAlt(_localctx, 1); - { - setState(57); - tileDefinition(); - } - break; - case SUBDIVISION: - enterOuterAlt(_localctx, 2); - { - setState(58); - subdivisionDefinition(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class TileDefinitionContext extends ParserRuleContext { - public TerminalNode TILETYPE() { return getToken(EscherParser.TILETYPE, 0); } - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public List NUMBER() { return getTokens(EscherParser.NUMBER); } - public TerminalNode NUMBER(int i) { - return getToken(EscherParser.NUMBER, i); - } - public TileDefinitionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_tileDefinition; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterTileDefinition(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitTileDefinition(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitTileDefinition(this); - else return visitor.visitChildren(this); - } - } - - public final TileDefinitionContext tileDefinition() throws RecognitionException { - TileDefinitionContext _localctx = new TileDefinitionContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_tileDefinition); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(61); - match(TILETYPE); - setState(62); - match(ID); - setState(63); - match(T__0); - setState(64); - match(NUMBER); - setState(69); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==T__1) { - { - { - setState(65); - match(T__1); - setState(66); - match(NUMBER); - } - } - setState(71); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(72); - match(T__2); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class SubdivisionDefinitionContext extends ParserRuleContext { - public TerminalNode SUBDIVISION() { return getToken(EscherParser.SUBDIVISION, 0); } - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public List subline() { - return getRuleContexts(SublineContext.class); - } - public SublineContext subline(int i) { - return getRuleContext(SublineContext.class,i); - } - public SubdivisionDefinitionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subdivisionDefinition; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterSubdivisionDefinition(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitSubdivisionDefinition(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitSubdivisionDefinition(this); - else return visitor.visitChildren(this); - } - } - - public final SubdivisionDefinitionContext subdivisionDefinition() throws RecognitionException { - SubdivisionDefinitionContext _localctx = new SubdivisionDefinitionContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_subdivisionDefinition); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(74); - match(SUBDIVISION); - setState(75); - match(ID); - setState(76); - match(T__0); - setState(78); - _errHandler.sync(this); - _la = _input.LA(1); - do { - { - { - setState(77); - subline(); - } - } - setState(80); - _errHandler.sync(this); - _la = _input.LA(1); - } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << CHILD) | (1L << VERTEX) | (1L << EDGE) | (1L << TILE) | (1L << SPLIT) | (1L << CONNECT))) != 0) ); - setState(82); - match(T__2); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ExpressionContext extends ParserRuleContext { - public FunctionContext function() { - return getRuleContext(FunctionContext.class,0); - } - public AssignmentContext assignment() { - return getRuleContext(AssignmentContext.class,0); - } - public ExpressionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_expression; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterExpression(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitExpression(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitExpression(this); - else return visitor.visitChildren(this); - } - } - - public final ExpressionContext expression() throws RecognitionException { - ExpressionContext _localctx = new ExpressionContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_expression); - try { - setState(86); - _errHandler.sync(this); - switch (_input.LA(1)) { - case TILE: - case SPLIT: - case CONNECT: - enterOuterAlt(_localctx, 1); - { - setState(84); - function(); - } - break; - case CHILD: - case VERTEX: - case EDGE: - enterOuterAlt(_localctx, 2); - { - setState(85); - assignment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class FunctionContext extends ParserRuleContext { - public TileFunctionContext tileFunction() { - return getRuleContext(TileFunctionContext.class,0); - } - public SplitFunctionContext splitFunction() { - return getRuleContext(SplitFunctionContext.class,0); - } - public ConnectFunctionContext connectFunction() { - return getRuleContext(ConnectFunctionContext.class,0); - } - public FunctionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_function; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterFunction(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitFunction(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitFunction(this); - else return visitor.visitChildren(this); - } - } - - public final FunctionContext function() throws RecognitionException { - FunctionContext _localctx = new FunctionContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_function); - try { - setState(91); - _errHandler.sync(this); - switch (_input.LA(1)) { - case TILE: - enterOuterAlt(_localctx, 1); - { - setState(88); - tileFunction(); - } - break; - case SPLIT: - enterOuterAlt(_localctx, 2); - { - setState(89); - splitFunction(); - } - break; - case CONNECT: - enterOuterAlt(_localctx, 3); - { - setState(90); - connectFunction(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class TileFunctionContext extends ParserRuleContext { - public TerminalNode TILE() { return getToken(EscherParser.TILE, 0); } - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public TerminalNode NUMBER() { return getToken(EscherParser.NUMBER, 0); } - public TileFunctionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_tileFunction; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterTileFunction(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitTileFunction(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitTileFunction(this); - else return visitor.visitChildren(this); - } - } - - public final TileFunctionContext tileFunction() throws RecognitionException { - TileFunctionContext _localctx = new TileFunctionContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_tileFunction); - try { - enterOuterAlt(_localctx, 1); - { - setState(93); - match(TILE); - setState(94); - match(T__3); - setState(95); - match(ID); - setState(96); - match(T__1); - setState(97); - match(NUMBER); - setState(98); - match(T__4); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class SplitFunctionContext extends ParserRuleContext { - public TerminalNode SPLIT() { return getToken(EscherParser.SPLIT, 0); } - public List node() { - return getRuleContexts(NodeContext.class); - } - public NodeContext node(int i) { - return getRuleContext(NodeContext.class,i); - } - public TerminalNode NUMBER() { return getToken(EscherParser.NUMBER, 0); } - public SplitFunctionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_splitFunction; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterSplitFunction(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitSplitFunction(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitSplitFunction(this); - else return visitor.visitChildren(this); - } - } - - public final SplitFunctionContext splitFunction() throws RecognitionException { - SplitFunctionContext _localctx = new SplitFunctionContext(_ctx, getState()); - enterRule(_localctx, 20, RULE_splitFunction); - try { - enterOuterAlt(_localctx, 1); - { - setState(100); - match(SPLIT); - setState(101); - match(T__3); - setState(102); - node(); - setState(103); - match(T__1); - setState(104); - node(); - setState(105); - match(T__1); - setState(106); - match(NUMBER); - setState(107); - match(T__4); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ConnectFunctionContext extends ParserRuleContext { - public TerminalNode CONNECT() { return getToken(EscherParser.CONNECT, 0); } - public List node() { - return getRuleContexts(NodeContext.class); - } - public NodeContext node(int i) { - return getRuleContext(NodeContext.class,i); - } - public ConnectFunctionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_connectFunction; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterConnectFunction(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitConnectFunction(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitConnectFunction(this); - else return visitor.visitChildren(this); - } - } - - public final ConnectFunctionContext connectFunction() throws RecognitionException { - ConnectFunctionContext _localctx = new ConnectFunctionContext(_ctx, getState()); - enterRule(_localctx, 22, RULE_connectFunction); - try { - enterOuterAlt(_localctx, 1); - { - setState(109); - match(CONNECT); - setState(110); - match(T__3); - setState(111); - node(); - setState(112); - match(T__1); - setState(113); - node(); - setState(114); - match(T__4); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class AssignmentContext extends ParserRuleContext { - public VertexAssignmentContext vertexAssignment() { - return getRuleContext(VertexAssignmentContext.class,0); - } - public EdgeAssignmentContext edgeAssignment() { - return getRuleContext(EdgeAssignmentContext.class,0); - } - public ChildAssignmentContext childAssignment() { - return getRuleContext(ChildAssignmentContext.class,0); - } - public AssignmentContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_assignment; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterAssignment(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitAssignment(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitAssignment(this); - else return visitor.visitChildren(this); - } - } - - public final AssignmentContext assignment() throws RecognitionException { - AssignmentContext _localctx = new AssignmentContext(_ctx, getState()); - enterRule(_localctx, 24, RULE_assignment); - try { - setState(119); - _errHandler.sync(this); - switch (_input.LA(1)) { - case VERTEX: - enterOuterAlt(_localctx, 1); - { - setState(116); - vertexAssignment(); - } - break; - case EDGE: - enterOuterAlt(_localctx, 2); - { - setState(117); - edgeAssignment(); - } - break; - case CHILD: - enterOuterAlt(_localctx, 3); - { - setState(118); - childAssignment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class VertexAssignmentContext extends ParserRuleContext { - public TerminalNode VERTEX() { return getToken(EscherParser.VERTEX, 0); } - public List ID() { return getTokens(EscherParser.ID); } - public TerminalNode ID(int i) { - return getToken(EscherParser.ID, i); - } - public SplitFunctionContext splitFunction() { - return getRuleContext(SplitFunctionContext.class,0); - } - public NodeContext node() { - return getRuleContext(NodeContext.class,0); - } - public VertexAssignmentContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_vertexAssignment; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterVertexAssignment(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitVertexAssignment(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitVertexAssignment(this); - else return visitor.visitChildren(this); - } - } - - public final VertexAssignmentContext vertexAssignment() throws RecognitionException { - VertexAssignmentContext _localctx = new VertexAssignmentContext(_ctx, getState()); - enterRule(_localctx, 26, RULE_vertexAssignment); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(121); - match(VERTEX); - setState(122); - match(ID); - setState(127); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==T__1) { - { - { - setState(123); - match(T__1); - setState(124); - match(ID); - } - } - setState(129); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(135); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==T__5) { - { - setState(130); - match(T__5); - setState(133); - _errHandler.sync(this); - switch (_input.LA(1)) { - case SPLIT: - { - setState(131); - splitFunction(); - } - break; - case ID: - { - setState(132); - node(); - } - break; - default: - throw new NoViableAltException(this); - } - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class EdgeAssignmentContext extends ParserRuleContext { - public TerminalNode EDGE() { return getToken(EscherParser.EDGE, 0); } - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public ConnectFunctionContext connectFunction() { - return getRuleContext(ConnectFunctionContext.class,0); - } - public List node() { - return getRuleContexts(NodeContext.class); - } - public NodeContext node(int i) { - return getRuleContext(NodeContext.class,i); - } - public EdgeAssignmentContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_edgeAssignment; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterEdgeAssignment(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitEdgeAssignment(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitEdgeAssignment(this); - else return visitor.visitChildren(this); - } - } - - public final EdgeAssignmentContext edgeAssignment() throws RecognitionException { - EdgeAssignmentContext _localctx = new EdgeAssignmentContext(_ctx, getState()); - enterRule(_localctx, 28, RULE_edgeAssignment); - try { - enterOuterAlt(_localctx, 1); - { - setState(137); - match(EDGE); - setState(138); - match(ID); - setState(147); - _errHandler.sync(this); - switch (_input.LA(1)) { - case T__5: - { - { - setState(139); - match(T__5); - setState(140); - connectFunction(); - } - } - break; - case T__3: - { - { - setState(141); - match(T__3); - setState(142); - node(); - setState(143); - match(T__1); - setState(144); - node(); - setState(145); - match(T__4); - } - } - break; - default: - throw new NoViableAltException(this); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ChildAssignmentContext extends ParserRuleContext { - public TerminalNode CHILD() { return getToken(EscherParser.CHILD, 0); } - public List ID() { return getTokens(EscherParser.ID); } - public TerminalNode ID(int i) { - return getToken(EscherParser.ID, i); - } - public List childList() { - return getRuleContexts(ChildListContext.class); - } - public ChildListContext childList(int i) { - return getRuleContext(ChildListContext.class,i); - } - public ChildAssignmentContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_childAssignment; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterChildAssignment(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitChildAssignment(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitChildAssignment(this); - else return visitor.visitChildren(this); - } - } - - public final ChildAssignmentContext childAssignment() throws RecognitionException { - ChildAssignmentContext _localctx = new ChildAssignmentContext(_ctx, getState()); - enterRule(_localctx, 30, RULE_childAssignment); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(149); - match(CHILD); - setState(150); - match(ID); - setState(151); - match(T__5); - setState(152); - match(ID); - setState(153); - match(T__3); - setState(155); - _errHandler.sync(this); - _la = _input.LA(1); - do { - { - { - setState(154); - childList(); - } - } - setState(157); - _errHandler.sync(this); - _la = _input.LA(1); - } while ( _la==T__6 ); - setState(159); - match(T__4); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class GraphAssignmentContext extends ParserRuleContext { - public TerminalNode GRAPH() { return getToken(EscherParser.GRAPH, 0); } - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public GraphDeclarationContext graphDeclaration() { - return getRuleContext(GraphDeclarationContext.class,0); - } - public GraphAssignmentContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_graphAssignment; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterGraphAssignment(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitGraphAssignment(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitGraphAssignment(this); - else return visitor.visitChildren(this); - } - } - - public final GraphAssignmentContext graphAssignment() throws RecognitionException { - GraphAssignmentContext _localctx = new GraphAssignmentContext(_ctx, getState()); - enterRule(_localctx, 32, RULE_graphAssignment); - try { - enterOuterAlt(_localctx, 1); - { - setState(161); - match(GRAPH); - setState(162); - match(ID); - setState(163); - match(T__5); - setState(164); - graphDeclaration(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class GraphDeclarationContext extends ParserRuleContext { - public TileFunctionContext tileFunction() { - return getRuleContext(TileFunctionContext.class,0); - } - public GraphDeclarationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_graphDeclaration; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterGraphDeclaration(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitGraphDeclaration(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitGraphDeclaration(this); - else return visitor.visitChildren(this); - } - } - - public final GraphDeclarationContext graphDeclaration() throws RecognitionException { - GraphDeclarationContext _localctx = new GraphDeclarationContext(_ctx, getState()); - enterRule(_localctx, 34, RULE_graphDeclaration); - try { - enterOuterAlt(_localctx, 1); - { - setState(166); - tileFunction(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class ChildListContext extends ParserRuleContext { - public List node() { - return getRuleContexts(NodeContext.class); - } - public NodeContext node(int i) { - return getRuleContext(NodeContext.class,i); - } - public ChildListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_childList; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterChildList(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitChildList(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitChildList(this); - else return visitor.visitChildren(this); - } - } - - public final ChildListContext childList() throws RecognitionException { - ChildListContext _localctx = new ChildListContext(_ctx, getState()); - enterRule(_localctx, 36, RULE_childList); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(168); - match(T__6); - setState(169); - node(); - setState(174); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==T__1) { - { - { - setState(170); - match(T__1); - setState(171); - node(); - } - } - setState(176); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(177); - match(T__7); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class NodeContext extends ParserRuleContext { - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public TerminalNode NUMBER() { return getToken(EscherParser.NUMBER, 0); } - public NodeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_node; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterNode(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitNode(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitNode(this); - else return visitor.visitChildren(this); - } - } - - public final NodeContext node() throws RecognitionException { - NodeContext _localctx = new NodeContext(_ctx, getState()); - enterRule(_localctx, 38, RULE_node); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(179); - match(ID); - setState(185); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==T__8) { - { - setState(180); - match(T__8); - setState(181); - match(T__9); - setState(182); - match(T__6); - setState(183); - match(NUMBER); - setState(184); - match(T__7); - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class FaceContext extends ParserRuleContext { - public TerminalNode ID() { return getToken(EscherParser.ID, 0); } - public TerminalNode NUMBER() { return getToken(EscherParser.NUMBER, 0); } - public FaceContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_face; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).enterFace(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof EscherListener ) ((EscherListener)listener).exitFace(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof EscherVisitor ) return ((EscherVisitor)visitor).visitFace(this); - else return visitor.visitChildren(this); - } - } - - public final FaceContext face() throws RecognitionException { - FaceContext _localctx = new FaceContext(_ctx, getState()); - enterRule(_localctx, 40, RULE_face); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(187); - match(ID); - setState(193); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==T__8) { - { - setState(188); - match(T__8); - setState(189); - match(T__10); - setState(190); - match(T__6); - setState(191); - match(NUMBER); - setState(192); - match(T__7); - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\32\u00c6\4\2\t\2"+ - "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ - "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ - "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\3\2\6\2.\n\2\r\2\16\2/\3\3\3"+ - "\3\3\3\3\4\3\4\3\4\3\5\3\5\5\5:\n\5\3\6\3\6\5\6>\n\6\3\7\3\7\3\7\3\7\3"+ - "\7\3\7\7\7F\n\7\f\7\16\7I\13\7\3\7\3\7\3\b\3\b\3\b\3\b\6\bQ\n\b\r\b\16"+ - "\bR\3\b\3\b\3\t\3\t\5\tY\n\t\3\n\3\n\3\n\5\n^\n\n\3\13\3\13\3\13\3\13"+ - "\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3"+ - "\r\3\r\3\r\3\16\3\16\3\16\5\16z\n\16\3\17\3\17\3\17\3\17\7\17\u0080\n"+ - "\17\f\17\16\17\u0083\13\17\3\17\3\17\3\17\5\17\u0088\n\17\5\17\u008a\n"+ - "\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u0096\n\20"+ - "\3\21\3\21\3\21\3\21\3\21\3\21\6\21\u009e\n\21\r\21\16\21\u009f\3\21\3"+ - "\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\24\3\24\3\24\3\24\7\24\u00af"+ - "\n\24\f\24\16\24\u00b2\13\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\5"+ - "\25\u00bc\n\25\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u00c4\n\26\3\26\2\2"+ - "\27\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*\2\2\2\u00c2\2-\3\2\2"+ - "\2\4\61\3\2\2\2\6\64\3\2\2\2\b9\3\2\2\2\n=\3\2\2\2\f?\3\2\2\2\16L\3\2"+ - "\2\2\20X\3\2\2\2\22]\3\2\2\2\24_\3\2\2\2\26f\3\2\2\2\30o\3\2\2\2\32y\3"+ - "\2\2\2\34{\3\2\2\2\36\u008b\3\2\2\2 \u0097\3\2\2\2\"\u00a3\3\2\2\2$\u00a8"+ - "\3\2\2\2&\u00aa\3\2\2\2(\u00b5\3\2\2\2*\u00bd\3\2\2\2,.\5\4\3\2-,\3\2"+ - "\2\2./\3\2\2\2/-\3\2\2\2/\60\3\2\2\2\60\3\3\2\2\2\61\62\5\b\5\2\62\63"+ - "\7\27\2\2\63\5\3\2\2\2\64\65\5\20\t\2\65\66\7\27\2\2\66\7\3\2\2\2\67:"+ - "\5\n\6\28:\5\20\t\29\67\3\2\2\298\3\2\2\2:\t\3\2\2\2;>\5\f\7\2<>\5\16"+ - "\b\2=;\3\2\2\2=<\3\2\2\2>\13\3\2\2\2?@\7\21\2\2@A\7\32\2\2AB\7\3\2\2B"+ - "G\7\31\2\2CD\7\4\2\2DF\7\31\2\2EC\3\2\2\2FI\3\2\2\2GE\3\2\2\2GH\3\2\2"+ - "\2HJ\3\2\2\2IG\3\2\2\2JK\7\5\2\2K\r\3\2\2\2LM\7\20\2\2MN\7\32\2\2NP\7"+ - "\3\2\2OQ\5\6\4\2PO\3\2\2\2QR\3\2\2\2RP\3\2\2\2RS\3\2\2\2ST\3\2\2\2TU\7"+ - "\5\2\2U\17\3\2\2\2VY\5\22\n\2WY\5\32\16\2XV\3\2\2\2XW\3\2\2\2Y\21\3\2"+ - "\2\2Z^\5\24\13\2[^\5\26\f\2\\^\5\30\r\2]Z\3\2\2\2][\3\2\2\2]\\\3\2\2\2"+ - "^\23\3\2\2\2_`\7\24\2\2`a\7\6\2\2ab\7\32\2\2bc\7\4\2\2cd\7\31\2\2de\7"+ - "\7\2\2e\25\3\2\2\2fg\7\25\2\2gh\7\6\2\2hi\5(\25\2ij\7\4\2\2jk\5(\25\2"+ - "kl\7\4\2\2lm\7\31\2\2mn\7\7\2\2n\27\3\2\2\2op\7\26\2\2pq\7\6\2\2qr\5("+ - "\25\2rs\7\4\2\2st\5(\25\2tu\7\7\2\2u\31\3\2\2\2vz\5\34\17\2wz\5\36\20"+ - "\2xz\5 \21\2yv\3\2\2\2yw\3\2\2\2yx\3\2\2\2z\33\3\2\2\2{|\7\22\2\2|\u0081"+ - "\7\32\2\2}~\7\4\2\2~\u0080\7\32\2\2\177}\3\2\2\2\u0080\u0083\3\2\2\2\u0081"+ - "\177\3\2\2\2\u0081\u0082\3\2\2\2\u0082\u0089\3\2\2\2\u0083\u0081\3\2\2"+ - "\2\u0084\u0087\7\b\2\2\u0085\u0088\5\26\f\2\u0086\u0088\5(\25\2\u0087"+ - "\u0085\3\2\2\2\u0087\u0086\3\2\2\2\u0088\u008a\3\2\2\2\u0089\u0084\3\2"+ - "\2\2\u0089\u008a\3\2\2\2\u008a\35\3\2\2\2\u008b\u008c\7\23\2\2\u008c\u0095"+ - "\7\32\2\2\u008d\u008e\7\b\2\2\u008e\u0096\5\30\r\2\u008f\u0090\7\6\2\2"+ - "\u0090\u0091\5(\25\2\u0091\u0092\7\4\2\2\u0092\u0093\5(\25\2\u0093\u0094"+ - "\7\7\2\2\u0094\u0096\3\2\2\2\u0095\u008d\3\2\2\2\u0095\u008f\3\2\2\2\u0096"+ - "\37\3\2\2\2\u0097\u0098\7\17\2\2\u0098\u0099\7\32\2\2\u0099\u009a\7\b"+ - "\2\2\u009a\u009b\7\32\2\2\u009b\u009d\7\6\2\2\u009c\u009e\5&\24\2\u009d"+ - "\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\u009d\3\2\2\2\u009f\u00a0\3\2"+ - "\2\2\u00a0\u00a1\3\2\2\2\u00a1\u00a2\7\7\2\2\u00a2!\3\2\2\2\u00a3\u00a4"+ - "\7\16\2\2\u00a4\u00a5\7\32\2\2\u00a5\u00a6\7\b\2\2\u00a6\u00a7\5$\23\2"+ - "\u00a7#\3\2\2\2\u00a8\u00a9\5\24\13\2\u00a9%\3\2\2\2\u00aa\u00ab\7\t\2"+ - "\2\u00ab\u00b0\5(\25\2\u00ac\u00ad\7\4\2\2\u00ad\u00af\5(\25\2\u00ae\u00ac"+ - "\3\2\2\2\u00af\u00b2\3\2\2\2\u00b0\u00ae\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1"+ - "\u00b3\3\2\2\2\u00b2\u00b0\3\2\2\2\u00b3\u00b4\7\n\2\2\u00b4\'\3\2\2\2"+ - "\u00b5\u00bb\7\32\2\2\u00b6\u00b7\7\13\2\2\u00b7\u00b8\7\f\2\2\u00b8\u00b9"+ - "\7\t\2\2\u00b9\u00ba\7\31\2\2\u00ba\u00bc\7\n\2\2\u00bb\u00b6\3\2\2\2"+ - "\u00bb\u00bc\3\2\2\2\u00bc)\3\2\2\2\u00bd\u00c3\7\32\2\2\u00be\u00bf\7"+ - "\13\2\2\u00bf\u00c0\7\r\2\2\u00c0\u00c1\7\t\2\2\u00c1\u00c2\7\31\2\2\u00c2"+ - "\u00c4\7\n\2\2\u00c3\u00be\3\2\2\2\u00c3\u00c4\3\2\2\2\u00c4+\3\2\2\2"+ - "\22/9=GRX]y\u0081\u0087\u0089\u0095\u009f\u00b0\u00bb\u00c3"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/tilings/language/grammar/EscherVisitor.java b/src/main/kotlin/tilings/language/grammar/EscherVisitor.java deleted file mode 100644 index da25a91..0000000 --- a/src/main/kotlin/tilings/language/grammar/EscherVisitor.java +++ /dev/null @@ -1,140 +0,0 @@ -package tilings.language.grammar; - -// Generated from Escher.g4 by ANTLR 4.7.1 -import org.antlr.v4.runtime.tree.ParseTreeVisitor; - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by {@link EscherParser}. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -public interface EscherVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by {@link EscherParser#file}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFile(EscherParser.FileContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#mainline}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitMainline(EscherParser.MainlineContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#subline}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSubline(EscherParser.SublineContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#phrase}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitPhrase(EscherParser.PhraseContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#definition}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitDefinition(EscherParser.DefinitionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#tileDefinition}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTileDefinition(EscherParser.TileDefinitionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#subdivisionDefinition}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSubdivisionDefinition(EscherParser.SubdivisionDefinitionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#expression}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitExpression(EscherParser.ExpressionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#function}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFunction(EscherParser.FunctionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#tileFunction}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTileFunction(EscherParser.TileFunctionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#splitFunction}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSplitFunction(EscherParser.SplitFunctionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#connectFunction}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitConnectFunction(EscherParser.ConnectFunctionContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#assignment}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitAssignment(EscherParser.AssignmentContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#vertexAssignment}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitVertexAssignment(EscherParser.VertexAssignmentContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#edgeAssignment}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitEdgeAssignment(EscherParser.EdgeAssignmentContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#childAssignment}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitChildAssignment(EscherParser.ChildAssignmentContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#graphAssignment}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitGraphAssignment(EscherParser.GraphAssignmentContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#graphDeclaration}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitGraphDeclaration(EscherParser.GraphDeclarationContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#childList}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitChildList(EscherParser.ChildListContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#node}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitNode(EscherParser.NodeContext ctx); - /** - * Visit a parse tree produced by {@link EscherParser#face}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFace(EscherParser.FaceContext ctx); -} \ No newline at end of file From 3f260f35ef2389a8d4e73f3be0f1f8381d71b200 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Sat, 30 Jun 2018 18:09:18 -0400 Subject: [PATCH 13/24] move gradle wrapper to default location --- .../wrapper/gradle-wrapper.jar | Bin 54329 -> 54413 bytes .../wrapper/gradle-wrapper.properties | 2 +- bin/gradlew => gradlew | 0 bin/gradlew.bat => gradlew.bat | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename {bin/gradle => gradle}/wrapper/gradle-wrapper.jar (81%) rename {bin/gradle => gradle}/wrapper/gradle-wrapper.properties (93%) rename bin/gradlew => gradlew (100%) rename bin/gradlew.bat => gradlew.bat (100%) diff --git a/bin/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar similarity index 81% rename from bin/gradle/wrapper/gradle-wrapper.jar rename to gradle/wrapper/gradle-wrapper.jar index 01b8bf6b1f99cad9213fc495b33ad5bbab8efd20..1948b9074f1016d15d505d185bc3f73deb82d8c8 100644 GIT binary patch delta 7399 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 Da{n=i delta 7286 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 KPzU?}WBw1fHw(7_ diff --git a/bin/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties similarity index 93% rename from bin/gradle/wrapper/gradle-wrapper.properties rename to gradle/wrapper/gradle-wrapper.properties index 933b647..d2c45a4 100644 --- a/bin/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip diff --git a/bin/gradlew b/gradlew similarity index 100% rename from bin/gradlew rename to gradlew diff --git a/bin/gradlew.bat b/gradlew.bat similarity index 100% rename from bin/gradlew.bat rename to gradlew.bat From aa40c3d136b36140dc5a90505cfd091dca7c5fee Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Sat, 30 Jun 2018 21:30:37 -0400 Subject: [PATCH 14/24] update build to generate run configs --- build.gradle | 42 ++++++++++++++++++------------------------ settings.gradle | 7 +++++++ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 45242b5..72b765f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,13 @@ plugins { id 'com.google.osdetector' version '1.4.0' - id 'org.jetbrains.kotlin.jvm' version '1.2.10' - id 'application' + id 'org.jetbrains.kotlin.jvm' version '1.2.50' id 'antlr' } // Set the main class for application and jar building -// - set in settings.gradle or +// - set in settings.gradle or // defined with -Pmain= in build command -mainClassName = project.findProperty('main') ?: gradle.ext.defaultClassName +ext.mainClassName = project.findProperty('main') ?: gradle.ext.defaultClassName // Use maven central repository for dependencies repositories { @@ -33,36 +32,28 @@ dependencies { antlr 'org.antlr:antlr4:4.7.1' } +// Ensures that the lib/jar folder exists for downloading cpcore.jar task chkLib { - group 'KoebeLib' - description 'Ensure that the jar directory exists' - doLast { def f = new File('lib/jar/') if (!f.exists()) { f.mkdirs() } } } +// Downloads cpcore.jar on Linux systems task get_nix(type:Exec, dependsOn:chkLib) { - group 'KoebeLib' - description 'Downloads CirclePack and extracts cpcore.jar; *nix' - workingDir 'lib/jar/' commandLine '../getCirclePack.sh' } +// Downloads cpcore.jar on Windows systems task get_win(type:Exec, dependsOn:chkLib) { - group 'KoebeLib' - description 'Downloads CirclePack and extracts cpcore.jar; Windows' - workingDir 'lib/jar/' commandLine 'powershell', '-ExecutionPolicy', 'RemoteSigned', '-c', '../getCirclePack.ps1' } +// Detects operating system and downloads cpcore.jar task get { - group 'KoebeLib' - description 'Detect OS for downloading CirclePack' - if (osdetector.os == 'windows') { dependsOn get_win } @@ -78,23 +69,26 @@ get_win.onlyIf { !cpcore.exists() } // Can't compile without cpcore.jar compileKotlin.dependsOn(get) +// Can't compile without Antlr grammar generated files compileKotlin.dependsOn(generateGrammarSource) -// Build jar with main class defined earlier -// Bundle all dependencies in the jar +// Build a fat jar with main class defined earlier jar { manifest { - attributes 'Main-Class' : project['mainClassName'] + attributes 'Main-Class' : project.mainClassName } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } } -task run(type: JavaExec, dependsOn: jar, overwrite: true) { - description 'Runs this project as a JVM application' - group 'application' +// Dynamically build run configurations for configured classes +gradle.ext.drivers.each { name, className -> + task "run$name" (type: JavaExec, dependsOn: jar, overwrite: true) { + description "Runs the ${name}.kt main class" + group "KoebeLib" - main project['mainClassName'] - classpath fileTree("$jar.destinationDir") + main "$className" + classpath fileTree("$jar.destinationDir") + } } diff --git a/settings.gradle b/settings.gradle index a213c6f..41695d0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,10 @@ rootProject.name='koebelib' // Define the default main class for the build gradle.ext.defaultClassName = 'sketches.SphericalSketchKt' + +// Define the main classes that will have run tasks generated +gradle.ext.drivers = [ + "SphericalSketch": "sketches.SphericalSketchKt", + "ConstructionSketch": "sketches.ConstructionSketchKt", + "TileView": "tilings.applications.TileViewKt" +] From 63ef751fe51fe94441e3541babf5eecb92952b07 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Sat, 30 Jun 2018 23:19:10 -0400 Subject: [PATCH 15/24] set explicit version for Kotlin stdlib to match gradle plugin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 72b765f..7959688 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ repositories { dependencies { // Kotlin standard library - compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.50' // KoebeLib dependencies compile files('lib/jar/cpcore.jar') From b3fe59417a282dc9a36442ea0ff59a78aea0c9b2 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Sat, 30 Jun 2018 23:55:36 -0400 Subject: [PATCH 16/24] Update README for new, stand-alone Gradle build system. --- README.md | 155 ++++++++++++++++++++++++------------------------ settings.gradle | 3 +- 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 02908df..cc566f1 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ # Koebe-Lib Development Environment -The purpose of this library is to support the creation of geometric constructions in the inversive -geometry of circles on the 2-sphere. The design of the code base was heavily influenced by Sherif Ghali's [Introduction to Geometric Computing](http://www.springer.com/us/book/9781848001145). This is an excellent reference for anyone interesting in coding a geometric library and gives a good overview of the various design decisions involved. Ghali also gives plenty of companion C++ code, which we referred to for coding several of the operations on various geometric objects and the structure of the `geometry.primitives` package is in line with Ghali's suggestion for how to structure such libraries. +The purpose of this library is to support the creation of geometric constructions in the inversive geometry of circles on the 2-sphere. +The design of the code base was heavily influenced by Sherif Ghali's [Introduction to Geometric Computing](http://www.springer.com/us/book/9781848001145). +This is an excellent reference for anyone interesting in coding a geometric library and gives a good overview of the various design decisions involved. +Ghali also gives plenty of companion C++ code, which we referred to for coding several of the operations on various geometric objects and the structure of the `geometry.primitives` package is in line with Ghali's suggestion for how to structure such libraries. -# App +# App -The code base also has one application (well, there are a few dummy ones that I need to remove/clean up) that is a first version of what I hope will eventually become a [GeoGebra](http://geogebra.org)-like application for inversive geometric constructions. That is the `SphericalSketch` found in the `sketches` package. This application loads a little bare-bones Python IDE and 3D view that allows a user to create and visualize geometric constructions on the fly. Eventually we will post some sample scripts somewhere in this repository. +The code base also has one application (well, there are a few dummy ones that I need to remove/clean up) that is a first version of what I hope will eventually become a [GeoGebra](http://geogebra.org)-like application for inversive geometric constructions. +That is the `SphericalSketch` found in the `sketches` package. +This application loads a little bare-bones Python IDE and 3D view that allows a user to create and visualize geometric constructions on the fly. +Eventually we will post some sample scripts somewhere in this repository. -# Codebase +# Codebase -This is a _very_ alpha-level release. I'm just getting started with this code base, and have some ideas for applications to build on top of it, but I decided to go ahead and release it, because some others are starting to use the code base and thus there needs to be a public repository. +This is a _very_ alpha-level release. +I'm just getting started with this code base, and have some ideas for applications to build on top of it, but I decided to go ahead and release it, because some others are starting to use the code base and thus there needs to be a public repository. -The codebase is written in Kotlin and is developed in JetBrain’s IDEA IntelliJ. - -Here is a set-up guide for getting a development environment up and running. - -The codebase has some weird dependencies. -They are all managed with Gradle and do not need to be retreived manually. +The codebase is written in Kotlin and is developed in JetBrain’s IntelliJ IDEA. +There are some weird dependencies, but they are all managed with Gradle and do not need to be retreived manually. - cpcore.jar 2.8 - Extracted from CirclePack [link](http://www.math.utk.edu/%7Ekens/CirclePack/downloads/) - jython-standalone 2.7.0 - [link](http://www.jython.org/downloads.html) @@ -26,70 +28,69 @@ They are all managed with Gradle and do not need to be retreived manually. - processing-core 3.3.6 - [link](https://processing.org/download/) - antlr4 4.7.1 - [link](https://www.antlr.org/download.html) -I have also included an ArcBall class that was converted to Kotlin and lightly modified. The -original can be found [here](https://github.com/RandomEtc/processing-arcball/). - -# Setting up the dev-environment. - -Dependency gathering and building is done with Gradle. -A local installation can be used, or a Gradle wrapper is available in the bin directory. -To use the wrapper substitute `../bin/gradlew` for `gradle` in the steps below. - -## Method 1: IntelliJ Project - -The goal of this method is to easily retrieve all dependency JARs and register them as dependencies in the IntelliJ project. -Building and Running is all done through IntelliJ's systems. - -### Step 1: Download dependencies -1. Clone the repo -2. In the `lib` directory run `gradle all` -3. This will download all dependencies to `/lib/jar` - -### Step 2: Create a new IntelliJ Project -1. Create a new project -2. Select 'Kotlin' in the left pane and 'Kotlin (JVM)' and click 'Next' -3. Name the project whatever you want, like 'Koebe-Lib' -4. Change the project location to the cloned repo and click 'Finish' - -### Step 3: Add dependencies to project -1. Open Project Structure dialog (Command+; or Ctrl+Shift+Alt+S) -2. Click 'Modules' and open the Dependencies tab -3. Click '+' and select 'JARs or directories...' -4. Select the `/lib/jar` folder -5. Click the 'Export' checkbox and click 'Apply' and 'OK' - -### Step 4: Create a runtime configuration. -1. Right click on the the `src/sketches/SphericalSketch.kt` file -2. Select the Run option - -## Method 2: Standalone Gradle build - -The goal of this method is to allow for building and running without using IntelliJ. - -### Configuration -All standalone building is done in the builder directory. -Configuration options are available in `settings.gradle` - -### Option 1: Build a JAR -1. From the `builder` directory run `gradle jar` -2. A standalone executable JAR will be built in `build/lib/koebelib.jar` -3. This can be run with `java -jar build/lib/koebelib.jar` - -### Option 2: Package a Distribution -1. From the `builder` directory run `gradle build` -2. A tarball and a zip file distribution will be built in `build/distibutions/koebelib.tar|zip` - -### Option 3: Install a Distribution -1. From the `builder` directory run `gradle install` -2. A distribution will be installed in `build/install/koebelib` -3. This can be run with the start script at `build/install/koebelib/bin/koebelib` - -### Option 4: Just compile (cannot be run) -1. From the `builder` directory run `gradle compileKotlin` - -#### Notes: -Because of how Gradle handles dependencies we cannot run the program from a gradle build -that has not been bundled in some form (ie options 1-3 above). -Attempting to use `gradle run` or other methods may result in missing native libraries. +I have also included an ArcBall class that was converted to Kotlin and lightly modified. The +original can be found [here](https://github.com/RandomEtc/processing-arcball/). + +# The dev-environment. + +Building and run configuration is all done through Gradle. +For use with IntelliJ IDEA the project should be imported as a Gradle project and built/run using the Gradle tasks. +Debugging through IntelliJ IDEA works as normal for Gradle tasks. +Tasks can be run with a local installation of Gradle, or using the included Gradle wrapper. +To use the wrapper substitute `./gradlew` for `gradle` in the examples below. + +### Configuration of run tasks +Configuration options are available in `settings.gradle` +Run configurations for new main classes can be created there. + +## Gradle tasks +Clone the repo. All Gradle tasks are run from the root of the repository. +View available tasks with the `gradle tasks` command. +The main tasks to use are described below. + +### Compile Kotlin +Run `gradle compileKotlin` +This compiles the source code with no additional actions taken. +This can be useful when just checking for compiler errors, but is generally not needed. + +### Generate ANTLR Grammar Sources +Run `gradle generateGrammarSource` +This will run ANTLR to generate source files for grammars in the `src/main/antlr/main` directory. +The files will be placed in `build/generated-src/antlr/main` if needed for reference. +This task is automatically run when compiling to make the ANTLR source available to the build. + +### Run the application +There are several run configurations available of the form `gradle run` +Each builds the application and runs their respective main class. + +### Build a JAR for distribution +Run `gradle jar` +A standalone executable 'fat' jar will be built in `build/lib/koebelib.jar` +This jar should be suitable for distribution as it includes all dependencies. +It can be run with `java -jar build/lib/koebelib.jar` +The main class is specified in `settings.gradle` or with the `-Pmain=` argument. + +### Cleanup the build directory +Run `gradle clean` +The build directory will be deleted. + +## Using IntelliJ IDEA + +1. Clone the repo. +2. Select import project in IntelliJ. +3. Select the `build.gradle` file from the cloned repo. +4. Configure import options. + - Check 'Use auto-import'. + - Uncheck 'Create separate module per source set' + - Select 'Use default gradle wrapper' or 'Use local gradle distribution' +5. Open the Gradle tool window. + - View > Tool Windows > Gradle +6. Select a run configuration + - Tasks > koebelib > run\ + +**_Disclaimer_** +Building the application and creating run configurations with IntelliJ's native tools may work. +It is, however, not supported and is not guaranteed to work in all cases. #koebe-lib + diff --git a/settings.gradle b/settings.gradle index 41695d0..81803d7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,7 +5,8 @@ gradle.ext.defaultClassName = 'sketches.SphericalSketchKt' // Define the main classes that will have run tasks generated gradle.ext.drivers = [ +// : , "SphericalSketch": "sketches.SphericalSketchKt", "ConstructionSketch": "sketches.ConstructionSketchKt", - "TileView": "tilings.applications.TileViewKt" + "TileView": "tilings.applications.TileViewKt", ] From b7ac824d249e77997e8b861042790ab3b94c37d7 Mon Sep 17 00:00:00 2001 From: maddiebrower Date: Thu, 26 Jul 2018 11:10:28 -0400 Subject: [PATCH 17/24] Added intersection tool. --- .../construction/BasicAlgorithmsS2.kt | 54 ++- src/gui/ConstructionGUI.kt | 7 + src/sketches/ConstructionSketch.kt | 429 +++++++++++++----- 3 files changed, 353 insertions(+), 137 deletions(-) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index d4c6798..d63738d 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -2,6 +2,7 @@ package geometry.construction import geometry.primitives.Euclidean3.VectorE3 import geometry.primitives.Spherical2.* +import geometry.primitives.OrientedProjective3.LineOP3 import java.awt.Point /** @@ -61,46 +62,63 @@ class TwoPointsToCoaxialFamilyS2() : IAlgorithm { class TwoDisksIntersectionPoint() : IAlgorithm> { override fun run(node: ConstructionNode>): List { - if (node.incoming.size != 2) { + if (node.incoming.size < 2) { throw InvalidConstructionParametersException("TwoDisksIntersectionPoint expects two DiskS2s. ${node.incoming.size} given.") } val disk1 = node.incoming[0].getOutput() as DiskS2 val disk2 = node.incoming[1].getOutput() as DiskS2 - val disk1Normal = VectorE3(disk1.a, disk1.b, disk1.c) - val disk2Normal = VectorE3(disk2.a, disk2.b, disk2.c) - val intersectionNormal = disk1Normal.cross(disk2Normal) - val point = pointOnPlanes(disk1, disk2) - - val tValues = solveForTValues(intersectionNormal, point) - - val point1 = PointS2(point.x + tValues[0]*intersectionNormal.x, point.y + tValues[0]*intersectionNormal.y, - point.z + tValues[0]*intersectionNormal.z) - - - val point2 = PointS2(point.x + tValues[1]*intersectionNormal.x, point.y + tValues[1]*intersectionNormal.y, - point.z + tValues[1]*intersectionNormal.z) - - var list = listOf(point1, point2) - - return list + //disk1.dualPlaneOP3 + //disk2.dualPlaneOP3 + var isectPoints = LineOP3(disk1.dualPlaneOP3, disk2.dualPlaneOP3).getIntersectionWithUnit2Sphere().map { + p -> PointS2(p.toVectorE3()) + } + return isectPoints +// val disk1Normal = VectorE3(disk1.a, disk1.b, disk1.c) +// System.out.println("disk1Norm " + disk1Normal.x + " " + disk1Normal.y + " " + disk1Normal.z) +// val disk2Normal = VectorE3(disk2.a, disk2.b, disk2.c) +// System.out.println("disk2Norm " + disk2Normal.x + " " + disk2Normal.y + " " + disk2Normal.z) +// val intersectionNormal = disk1Normal.cross(disk2Normal) +// System.out.println("intersectNorm " + intersectionNormal.x + " " + intersectionNormal.y + " " + intersectionNormal.z) +// val point = pointOnPlanes(disk1, disk2) +// System.out.println("point " + point.x + " " + point.y + " " + point.z) +// +// val tValues = solveForTValues(intersectionNormal, point) +// +// val point1 = PointS2(point.x + tValues[0]*intersectionNormal.x, point.y + tValues[0]*intersectionNormal.y, +// point.z + tValues[0]*intersectionNormal.z) +// +// +// val point2 = PointS2(point.x + tValues[1]*intersectionNormal.x, point.y + tValues[1]*intersectionNormal.y, +// point.z + tValues[1]*intersectionNormal.z) +// +// var list = listOf(point1, point2) +// return list } fun solveForTValues(intersectionNormal : VectorE3, point : PointS2) : MutableList{ val bCoefficient = (2*point.x*intersectionNormal.x + 2*point.y*intersectionNormal.y + 2*point.z*intersectionNormal.z) + System.out.println("b " + bCoefficient) val aCoefficient = intersectionNormal.x*intersectionNormal.x + intersectionNormal.y*intersectionNormal.y + intersectionNormal.z*intersectionNormal.z + System.out.println("a " + aCoefficient) val cCoefficient = point.x*point.x + point.y*point.y + point.z*point.z - 1 + System.out.println("c " + cCoefficient) val denom = 2*aCoefficient + System.out.println("denom " + denom) var t1Numerator = -bCoefficient + Math.sqrt(Math.pow(bCoefficient,2.0) - 4*aCoefficient*cCoefficient) + System.out.println("t1Num " + t1Numerator ) var t1 = t1Numerator/denom + System.out.println("t1 " + t1) var t2Numerator = -bCoefficient - Math.sqrt(Math.pow(bCoefficient,2.0) - 4*aCoefficient*cCoefficient) + System.out.println("t2Num " + t2Numerator ) var t2 = t2Numerator/denom + System.out.println("t2 " + t2) var list = mutableListOf() list.add(t1) diff --git a/src/gui/ConstructionGUI.kt b/src/gui/ConstructionGUI.kt index 23264df..f94b78c 100644 --- a/src/gui/ConstructionGUI.kt +++ b/src/gui/ConstructionGUI.kt @@ -25,6 +25,7 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { val pointButton : JButton val circleButton : JButton val selectionButton : JButton + val intersectButton : JButton init { // Build the GUI: @@ -42,11 +43,13 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { pointButton = JButton("point") circleButton = JButton("circle") selectionButton = JButton("Select") + intersectButton = JButton("Intersection") buttonFlowPanel.add(arcballButton) buttonFlowPanel.add(pointButton) buttonFlowPanel.add(circleButton) buttonFlowPanel.add(selectionButton) + buttonFlowPanel.add(intersectButton) buttonPanel.add(buttonFlowPanel, BorderLayout.WEST) this.contentPane.add(buttonPanel, BorderLayout.PAGE_START) @@ -66,6 +69,10 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { selectionButton.addActionListener { sketch.currentTool = SelectionTool(sketch) } + + intersectButton.addActionListener { + sketch.currentTool = IntersectionTool(sketch) + } } } diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index c7451ca..2c69f67 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -104,6 +104,135 @@ class ArcballTool(val arcball: Arcball?) : MouseTool() { } } +class IntersectionTool(val sketch : ConstructionSketch ) : MouseTool() { + var selectedDisks = mutableListOf>() + + fun transform(mouseX: Int, mouseY: Int) : PointE3{ + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + + var l = PointE3.O - new1 + + var tca = l.dot(direction) + var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) + var thc = Math.sqrt(1 - d * d) + var t0 = tca - thc + var t1 = tca + thc + var inter = PointE3(0.0, 0.0, 0.0) + if (t0 > t1) { + inter = new1 + direction * t1 + return inter + } else { + inter = new1 + direction * t0 + return inter + } + } + return PointE3() + } + + fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + var rayOrigin = VectorE3(new1.x, new1.y, new1.z) + var worldOrigin = VectorE3(0.0, 0.0, 0.0) + var normalVector = VectorE3(a, b, c) + var denom = direction.dot(normalVector) + var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom + return t >= 0 + } + + return false; + } + + fun diskIntersection(disk1 : DiskS2, disk2 : DiskS2) : Boolean { + //TODO: calculate the intersection of two points + return false; + } + + override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) + var cursor = transform(mouseX, mouseY) + //var selectedNode: Any? = null + if(cursor!= null) { + for(node in sketch.construction.nodes) { + var output = node.getOutput() + if (output is DiskS2) { + var a = output.a + var b = output.b + var c = output.c + var d = output.d + if(isIntersection(mouseX, mouseY, a, b, c, d)) { + if(!selectedDisks.contains(node)) { + selectedDisks.add(node as INode) + break + } + } + } + } + } + + } + override fun mouseReleased(mouseX: Int, mouseY: Int) { + super.mouseReleased(mouseX, mouseY) + if(selectedDisks.size >= 2) { + var obj1 = selectedDisks[0] + var obj2 = selectedDisks[1] + //if(diskIntersection(obj1.getOutput(), obj2.getOutput())) { + sketch.construction.makeIntersectionPoint(obj1, obj2) + //} + } + } + override fun mouseDragged(mouseX: Int, mouseY: Int) { + } + override fun mouseClicked(mouseX: Int, mouseY: Int) { + + } + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } +} class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { fun transform(mouseX: Int, mouseY: Int) : PointE3{ val gl = sketch.g @@ -184,6 +313,7 @@ class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { return false; } + //TODO: need to get minimum distance and then set node also add a feature to select multiple things override fun mouseClicked(mouseX: Int, mouseY: Int) { var cursor = transform(mouseX, mouseY) @@ -235,7 +365,6 @@ class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { var selectedNode : INode<*>? = null; - var selectedNodes = mutableListOf>() fun transform(mouseX: Int, mouseY: Int): PointE3 { val gl = sketch.g @@ -331,6 +460,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { if(node != null) { var output = node.getOutput() if (output is PointS2) { + //TODO: this needs to change so you get the closest one not the fist within a delta if (Math.abs(cursor.x.toFloat() - output.x) <= .1 && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { @@ -341,19 +471,65 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { } } if (drawNode) { - val node = sketch.construction.makePointS2(cursor.x, cursor.y, cursor.z) + sketch.construction.makePointS2(cursor.x, cursor.y, cursor.z) } } } - class CircleTool(sketch: ConstructionSketch) : PointEditorTool(sketch) { + class CircleTool(val sketch: ConstructionSketch) : MouseTool() { + var selectedNode : INode<*>? = null; + var selectedNodes = mutableListOf>() + + fun transform(mouseX: Int, mouseY: Int): PointE3 { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + + var l = PointE3.O - new1 + + var tca = l.dot(direction) + var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) + var thc = Math.sqrt(1 - d * d) + var t0 = tca - thc + var t1 = tca + thc + var inter = PointE3(0.0, 0.0, 0.0) + if (t0 > t1) { + inter = new1 + direction * t1 + return inter + } else { + inter = new1 + direction * t0 + return inter + } + } + return PointE3() + } + override fun mousePressed(mouseX: Int, mouseY: Int) { super.mousePressed(mouseX, mouseY) var cursor = transform(mouseX, mouseY) if (cursor != null) { - for (node in sketch.construction.nodes) { if (node != null) { var output = node.getOutput() @@ -365,7 +541,10 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { selectedNode = node node.style = Style(Color.noColor, Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) - break + if(!selectedNodes.contains(selectedNode as INode<*>)) { + selectedNodes.add(selectedNode as INode<*>) + break + } } } @@ -373,7 +552,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { } } - selectedNodes.add(selectedNode as INode<*>) + } override fun mouseMoved(mouseX: Int, mouseY: Int) { @@ -395,6 +574,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { var node = sketch.construction.makeDiskS2( obj1 as INode, obj2 as INode, obj3 as INode) + selectedNodes.removeAll({true}) } } @@ -482,121 +662,14 @@ open class ConstructionSketch : SphericalSketch() { val style = if (consStyles[it] is Style) consStyles[it] as Style else objectStyles[it] - when (it) { - is PointS2 -> { - if (style != null) style.set(this) - else { - noStroke() - fill(100.0f, 125.0f, 255.0f) - } - drawPointE3(it.directionE3.endPoint) - } - is PointE2 -> { - if (style != null) style.set(this) - else { - noStroke() - fill(100.0f, 125.0f, 255.0f) - } - drawPointE2(it) - } - is DiskOP2 -> { - if (style != null) style.set(this) - else { - stroke(0.0f, 0.0f, 0.0f) - noFill() - } - drawDiskOP2(it) - } - is LineOP2 -> { - if (style != null) style.set(this) - else { - stroke(0.0f, 0.0f, 0.0f) - noFill() - } - drawLineOP2(it) - } - is PointE3 -> { - if (style != null) style.set(this) - else { - noStroke() - fill(100.0f, 125.0f, 255.0f) - } - drawPointE3(it) - } - is PointOP2 -> { - if (style != null) style.set(this) - else { - noStroke() - fill(100.0f, 125.0f, 255.0f) - } - drawPointOP2(it) - } - - is PointOP3 -> { - if (style != null) style.set(this) - else { - noStroke() - fill(100.0f, 125.0f, 255.0f) - } - if (!it.isIdeal()) drawPointE3(it.toPointE3()) - } - is DiskS2 -> { - if (style != null) style.set(this) - else { - stroke(0) - } - drawCircleS2(it) + if(it is List<*>) { + it.forEach { + obj -> drawGeometricObjects(obj, style) } - is DiskE2 -> { - if (style != null) style.set(this) - else { - stroke(0) - } - drawCircleE2(it) - } - is CircleArcOP2 -> { - if (style != null) style.set(this) - else { - stroke(0.0f, 0.0f, 255.0f) - } - drawCircleArcOP2(it) - if (style == null) { - noStroke() - fill(255.0f, 0.0f, 125.0f) - drawPointOP2(it.source) - drawPointOP2(it.target) - } - } - is CircleArcS2 -> { - if (style != null) style.set(this) - else { - stroke(0.0f, 0.0f, 255.0f) - } - drawCircleArcS2(it) - if (style == null) { - noStroke() - fill(255.0f, 0.0f, 125.0f) - drawPointE3(it.source.directionE3.endPoint) - drawPointE3(it.target.directionE3.endPoint) - } - } - is CPlaneS2 -> { - if (style != null) style.set(this) - else { - stroke(255.0f, 0.0f, 0.0f) - } - drawCircleS2(it.dualDiskS2) - } - is DCEL<*, *, *> -> { - if (style != null) style.set(this) - else { - stroke(0) - fill(255.0f, 255.0f, 255.0f) - } - drawDCEL(it) - } - else -> {} + } else { + drawGeometricObjects(it, style) } + } } }) @@ -675,6 +748,124 @@ open class ConstructionSketch : SphericalSketch() { } } + fun drawGeometricObjects(it : Any?, style: Style?) { + when (it) { + is PointS2 -> { + if (style != null) style.set(this) + else { + noStroke() + fill(100.0f, 125.0f, 255.0f) + } + drawPointE3(it.directionE3.endPoint) + } + is PointE2 -> { + if (style != null) style.set(this) + else { + noStroke() + fill(100.0f, 125.0f, 255.0f) + } + drawPointE2(it) + } + is DiskOP2 -> { + if (style != null) style.set(this) + else { + stroke(0.0f, 0.0f, 0.0f) + noFill() + } + drawDiskOP2(it) + } + is LineOP2 -> { + if (style != null) style.set(this) + else { + stroke(0.0f, 0.0f, 0.0f) + noFill() + } + drawLineOP2(it) + } + is PointE3 -> { + if (style != null) style.set(this) + else { + noStroke() + fill(100.0f, 125.0f, 255.0f) + } + drawPointE3(it) + } + is PointOP2 -> { + if (style != null) style.set(this) + else { + noStroke() + fill(100.0f, 125.0f, 255.0f) + } + drawPointOP2(it) + } + + is PointOP3 -> { + if (style != null) style.set(this) + else { + noStroke() + fill(100.0f, 125.0f, 255.0f) + } + if (!it.isIdeal()) drawPointE3(it.toPointE3()) + } + is DiskS2 -> { + if (style != null) style.set(this) + else { + stroke(0) + } + drawCircleS2(it) + } + is DiskE2 -> { + if (style != null) style.set(this) + else { + stroke(0) + } + drawCircleE2(it) + } + is CircleArcOP2 -> { + if (style != null) style.set(this) + else { + stroke(0.0f, 0.0f, 255.0f) + } + drawCircleArcOP2(it) + if (style == null) { + noStroke() + fill(255.0f, 0.0f, 125.0f) + drawPointOP2(it.source) + drawPointOP2(it.target) + } + } + is CircleArcS2 -> { + if (style != null) style.set(this) + else { + stroke(0.0f, 0.0f, 255.0f) + } + drawCircleArcS2(it) + if (style == null) { + noStroke() + fill(255.0f, 0.0f, 125.0f) + drawPointE3(it.source.directionE3.endPoint) + drawPointE3(it.target.directionE3.endPoint) + } + } + is CPlaneS2 -> { + if (style != null) style.set(this) + else { + stroke(255.0f, 0.0f, 0.0f) + } + drawCircleS2(it.dualDiskS2) + } + is DCEL<*, *, *> -> { + if (style != null) style.set(this) + else { + stroke(0) + fill(255.0f, 255.0f, 255.0f) + } + drawDCEL(it) + } + else -> {} + } + } + From eb50aac6d9ce7fd8e99d1ddd24d53ea4c3db8b2f Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Thu, 26 Jul 2018 15:06:29 -0400 Subject: [PATCH 18/24] Bad commit. Adding new tool from MaddieBranch to MaddieBranch2 --- src/sketches/ConstructionSketch.kt | 143 +++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 2c69f67..729044b 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -581,7 +581,150 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { } } +open class CoaxialPointTool(val sketch: ConstructionSketch) : MouseTool() { + var selectedNode : INode<*>? = null; + var selectedNodes = mutableListOf>() + + fun transform(mouseX: Int, mouseY: Int): PointE3 { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + + var l = PointE3.O - new1 + + var tca = l.dot(direction) + var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) + var thc = Math.sqrt(1 - d * d) + var t0 = tca - thc + var t1 = tca + thc + var inter = PointE3(0.0, 0.0, 0.0) + if (t0 > t1) { + inter = new1 + direction * t1 + return inter + } else { + inter = new1 + direction * t0 + return inter + } + } + return PointE3() + } + + fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + var rayOrigin = VectorE3(new1.x, new1.y, new1.z) + var worldOrigin = VectorE3(0.0, 0.0, 0.0) + var normalVector = VectorE3(a, b, c) + var denom = direction.dot(normalVector) + var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom + return t >= 0 + } + + return false; + } + + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } + + override fun mouseDragged(mouseX: Int, mouseY: Int) { + + } + + override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) + var cursor = transform(mouseX, mouseY) + if (cursor != null) { + + for (node in sketch.construction.nodes) { + if (node != null) { + var output = node.getOutput() + if (output is PointS2 && !selectedNodes.isEmpty()) { + //TODO: should change this so its the closet found point + if (Math.abs(cursor.x.toFloat() - output.x) <= .1 + && Math.abs(cursor.y.toFloat() - output.y) <= .1 + && Math.abs(cursor.z.toFloat() - output.z) <= .1) { + + selectedNode = node + node.style = Style(Color(255.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) + break + } + } + if (output is DiskS2) { + var a = output.a + var b = output.b + var c = output.c + var d = output.d + if(isIntersection(mouseX, mouseY, a, b, c, d)) {selectedNode = node + selectedNode = node + node.style = Style(Color(200.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) + } + } + + } + } + } + + selectedNodes.add(selectedNode as INode<*>) + } + + override fun mouseReleased(mouseX: Int, mouseY: Int) { + super.mouseReleased(mouseX, mouseY) + if (selectedNodes.size >= 3) { + var obj1 = selectedNodes[0] + var obj2 = selectedNodes[1] + var obj3 = selectedNodes[2] + + @Suppress("UNCHECKED_CAST") + var node = sketch.construction.makeDiskS2( obj1 as INode, + obj2 as INode, + obj3 as INode) + + } + } +} open class ConstructionSketch : SphericalSketch() { From fd6c347ffe00398ab34fb9506525647c82ddeb70 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Wed, 1 Aug 2018 21:35:42 -0400 Subject: [PATCH 19/24] rearrange upstream to fit new src structure --- src/{ => main/kotlin}/tilings/language/algorithms/EscherDriver.kt | 0 src/{ => main/kotlin}/tilings/language/algorithms/planarDraw.py | 0 src/{ => main/kotlin}/tilings/language/gui/EscherFrame.kt | 0 src/{ => main/kotlin}/tilings/language/gui/TileSketch.kt | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => main/kotlin}/tilings/language/algorithms/EscherDriver.kt (100%) rename src/{ => main/kotlin}/tilings/language/algorithms/planarDraw.py (100%) rename src/{ => main/kotlin}/tilings/language/gui/EscherFrame.kt (100%) rename src/{ => main/kotlin}/tilings/language/gui/TileSketch.kt (100%) diff --git a/src/tilings/language/algorithms/EscherDriver.kt b/src/main/kotlin/tilings/language/algorithms/EscherDriver.kt similarity index 100% rename from src/tilings/language/algorithms/EscherDriver.kt rename to src/main/kotlin/tilings/language/algorithms/EscherDriver.kt diff --git a/src/tilings/language/algorithms/planarDraw.py b/src/main/kotlin/tilings/language/algorithms/planarDraw.py similarity index 100% rename from src/tilings/language/algorithms/planarDraw.py rename to src/main/kotlin/tilings/language/algorithms/planarDraw.py diff --git a/src/tilings/language/gui/EscherFrame.kt b/src/main/kotlin/tilings/language/gui/EscherFrame.kt similarity index 100% rename from src/tilings/language/gui/EscherFrame.kt rename to src/main/kotlin/tilings/language/gui/EscherFrame.kt diff --git a/src/tilings/language/gui/TileSketch.kt b/src/main/kotlin/tilings/language/gui/TileSketch.kt similarity index 100% rename from src/tilings/language/gui/TileSketch.kt rename to src/main/kotlin/tilings/language/gui/TileSketch.kt From ed0d7bf4d21dba9000ae7834054abab2757d1abe Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Wed, 1 Aug 2018 21:36:15 -0400 Subject: [PATCH 20/24] new run config --- settings.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle b/settings.gradle index 81803d7..95dc5b4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,4 +9,5 @@ gradle.ext.drivers = [ "SphericalSketch": "sketches.SphericalSketchKt", "ConstructionSketch": "sketches.ConstructionSketchKt", "TileView": "tilings.applications.TileViewKt", + "TileSketch": "tilings.language.gui.TileSketchKt", ] From f4c8cfa7f6c236bc49715f147f9b43aa1a0f4b70 Mon Sep 17 00:00:00 2001 From: Madelaine Brower Date: Mon, 13 Aug 2018 15:30:21 -0400 Subject: [PATCH 21/24] Fixed bugs in the Coaxial point tool now working correctly. --- .../construction/BasicAlgorithmsS2.kt | 33 +++++++ src/geometry/construction/Construction.kt | 4 + src/gui/ConstructionGUI.kt | 7 ++ src/sketches/ConstructionSketch.kt | 97 +++++++++---------- 4 files changed, 90 insertions(+), 51 deletions(-) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index d63738d..014c583 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -60,6 +60,39 @@ class TwoPointsToCoaxialFamilyS2() : IAlgorithm { } } +class TwoDisksPointCoaxialCircle() : IAlgorithm { + override fun run(node: ConstructionNode): DiskS2 { + if (node.incoming.size != 3) { + throw InvalidConstructionParametersException("TwoDisksPointCoaxialCircle expects two DiskS2s and one PointS2. ${node.incoming.size} given.") + + } + + val disk1 = node.incoming[0].getOutput() as DiskS2 + val disk2 = node.incoming[1].getOutput() as DiskS2 + val point = node.incoming[2].getOutput() as PointS2 + val pointVector = point.directionE3.v.normalize() + val a1 = disk1.a + val b1 = disk1.b + val c1 = disk1.c + val d1 = disk1.d + val a2 = disk2.a + val b2 = disk2.b + val c2 = disk2.c + val d2 = disk2.d + val x = pointVector.x + val y = pointVector.y + val z = pointVector.z + val w = 1 + + val a = a2 * (d1 * w + b1 * y + c1 * z) - a1 * (d2 * w + b2 * y + c2 * z) + val b = b2 * (d1 * w + a1 * x + c1 * z) - b1 * (d2 * w + a2 * x + c2 * z) + val c = c2 * (d1 * w + a1 * x + b1 * y) - c1 * (d2 * w + a2 * x + b2 * y) + val d = -a2 * d1 * x + d2 * (a1 * x + b1 * y + c1 * z) - d1 * (b2 * y + c2 * z) + + return DiskS2(a, b, c, d) + } +} + class TwoDisksIntersectionPoint() : IAlgorithm> { override fun run(node: ConstructionNode>): List { if (node.incoming.size < 2) { diff --git a/src/geometry/construction/Construction.kt b/src/geometry/construction/Construction.kt index 63967e1..c055e47 100644 --- a/src/geometry/construction/Construction.kt +++ b/src/geometry/construction/Construction.kt @@ -45,6 +45,10 @@ class Construction { fun makeIntersectionPoint(disk1: INode, disk2: INode) { ConstructionNode>(this, listOf(disk1, disk2), TwoDisksIntersectionPoint(), null) } + + fun makeCoaxialDisk(disk1 : INode, disk2: INode, point: INode) { + ConstructionNode(this, listOf(disk1, disk2, point), TwoDisksPointCoaxialCircle(), null) + } } diff --git a/src/gui/ConstructionGUI.kt b/src/gui/ConstructionGUI.kt index f94b78c..02fb096 100644 --- a/src/gui/ConstructionGUI.kt +++ b/src/gui/ConstructionGUI.kt @@ -26,6 +26,7 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { val circleButton : JButton val selectionButton : JButton val intersectButton : JButton + val disksPointCoaxialDisk: JButton init { // Build the GUI: @@ -44,12 +45,14 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { circleButton = JButton("circle") selectionButton = JButton("Select") intersectButton = JButton("Intersection") + disksPointCoaxialDisk = JButton("CoaxialFamilyDisk") buttonFlowPanel.add(arcballButton) buttonFlowPanel.add(pointButton) buttonFlowPanel.add(circleButton) buttonFlowPanel.add(selectionButton) buttonFlowPanel.add(intersectButton) + buttonFlowPanel.add(disksPointCoaxialDisk) buttonPanel.add(buttonFlowPanel, BorderLayout.WEST) this.contentPane.add(buttonPanel, BorderLayout.PAGE_START) @@ -73,6 +76,10 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { intersectButton.addActionListener { sketch.currentTool = IntersectionTool(sketch) } + + disksPointCoaxialDisk.addActionListener { + sketch.currentTool = CoaxialPointTool(sketch) + } } } diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index 729044b..fcaf037 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -186,16 +186,12 @@ class IntersectionTool(val sketch : ConstructionSketch ) : MouseTool() { return false; } - fun diskIntersection(disk1 : DiskS2, disk2 : DiskS2) : Boolean { - //TODO: calculate the intersection of two points - return false; - } override fun mousePressed(mouseX: Int, mouseY: Int) { super.mousePressed(mouseX, mouseY) var cursor = transform(mouseX, mouseY) - //var selectedNode: Any? = null - if(cursor!= null) { + + if(cursor != null) { for(node in sketch.construction.nodes) { var output = node.getOutput() if (output is DiskS2) { @@ -219,9 +215,7 @@ class IntersectionTool(val sketch : ConstructionSketch ) : MouseTool() { if(selectedDisks.size >= 2) { var obj1 = selectedDisks[0] var obj2 = selectedDisks[1] - //if(diskIntersection(obj1.getOutput(), obj2.getOutput())) { - sketch.construction.makeIntersectionPoint(obj1, obj2) - //} + sketch.construction.makeIntersectionPoint(obj1, obj2) } } override fun mouseDragged(mouseX: Int, mouseY: Int) { @@ -314,10 +308,22 @@ class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { } - //TODO: need to get minimum distance and then set node also add a feature to select multiple things override fun mouseClicked(mouseX: Int, mouseY: Int) { + + } + + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } + + override fun mouseDragged(mouseX: Int, mouseY: Int) { + + } + + //TODO: need to get minimum distance and then set node also add a feature to select multiple things + override fun mousePressed(mouseX: Int, mouseY: Int) { var cursor = transform(mouseX, mouseY) - //var selectedNode: Any? = null + if(cursor!= null) { for(node in sketch.construction.nodes) { var output = node.getOutput() @@ -342,19 +348,6 @@ class SelectionTool(val sketch : ConstructionSketch) : MouseTool() { } } } - //(selectedNode as INode<*>).style = Style() - } - - override fun mouseMoved(mouseX: Int, mouseY: Int) { - super.mouseMoved(mouseX, mouseY) - } - - override fun mouseDragged(mouseX: Int, mouseY: Int) { - - } - - override fun mousePressed(mouseX: Int, mouseY: Int) { - super.mousePressed(mouseX, mouseY) } override fun mouseReleased(mouseX: Int, mouseY: Int) { @@ -423,7 +416,7 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { if (node != null) { var output = node.getOutput() if (output is PointS2) { - //should change this so its the closet found point + //TODO: should change this so its the closet found point if (Math.abs(cursor.x.toFloat() - output.x) <= .1 && Math.abs(cursor.y.toFloat() - output.y) <= .1 && Math.abs(cursor.z.toFloat() - output.z) <= .1) { @@ -547,12 +540,9 @@ open class PointEditorTool(val sketch: ConstructionSketch) : MouseTool() { } } } - } } } - - } override fun mouseMoved(mouseX: Int, mouseY: Int) { @@ -675,39 +665,44 @@ open class CoaxialPointTool(val sketch: ConstructionSketch) : MouseTool() { override fun mousePressed(mouseX: Int, mouseY: Int) { super.mousePressed(mouseX, mouseY) - var cursor = transform(mouseX, mouseY) + val cursor = transform(mouseX, mouseY) if (cursor != null) { - + var minDist = 100.0 for (node in sketch.construction.nodes) { if (node != null) { - var output = node.getOutput() - if (output is PointS2 && !selectedNodes.isEmpty()) { - //TODO: should change this so its the closet found point - if (Math.abs(cursor.x.toFloat() - output.x) <= .1 - && Math.abs(cursor.y.toFloat() - output.y) <= .1 - && Math.abs(cursor.z.toFloat() - output.z) <= .1) { - + val output = node.getOutput() + if (output is PointS2) { + val dist = Math.sqrt(Math.pow(output.x - cursor.x, 2.0) + Math.pow(output.y - cursor.y, 2.0) + + Math.pow(output.z - cursor.z, 2.0)) + if (dist < minDist) { + minDist = dist selectedNode = node - node.style = Style(Color(255.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) - break } } if (output is DiskS2) { - var a = output.a - var b = output.b - var c = output.c - var d = output.d - if(isIntersection(mouseX, mouseY, a, b, c, d)) {selectedNode = node - selectedNode = node - node.style = Style(Color(200.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) + val a = output.a + val b = output.b + val c = output.c + val d = output.d + if(isIntersection(mouseX, mouseY, a, b, c, d)) { + val center = output.centerE3 + val radius = output.radiusE3 + val diskDist = Math.sqrt(Math.pow(center.x - cursor.x, 2.0) + Math.pow(center.y - cursor.y, 2.0) + + Math.pow(center.z - cursor.z, 2.0)) - radius + if (diskDist < minDist) { + minDist = diskDist + selectedNode = node + } } } - } } - } - selectedNodes.add(selectedNode as INode<*>) + selectedNode?.style = Style(Color(200.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) + if(!selectedNodes.contains(selectedNode)) { + selectedNodes.add(selectedNode as INode<*>) + } + } } override fun mouseReleased(mouseX: Int, mouseY: Int) { @@ -718,8 +713,8 @@ open class CoaxialPointTool(val sketch: ConstructionSketch) : MouseTool() { var obj3 = selectedNodes[2] @Suppress("UNCHECKED_CAST") - var node = sketch.construction.makeDiskS2( obj1 as INode, - obj2 as INode, + var node = sketch.construction.makeCoaxialDisk( obj1 as INode, + obj2 as INode, obj3 as INode) } From 38f4d0f54428f4c0fb9372598306129405a3a450 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Wed, 6 Feb 2019 12:20:21 -0500 Subject: [PATCH 22/24] Update library versions --- build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 7959688..e907781 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'com.google.osdetector' version '1.4.0' - id 'org.jetbrains.kotlin.jvm' version '1.2.50' + id 'org.jetbrains.kotlin.jvm' version '1.3.21' id 'antlr' } @@ -16,7 +16,7 @@ repositories { dependencies { // Kotlin standard library - compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.50' + compile 'org.jetbrains.kotlin:kotlin-stdlib:1.3.21' // KoebeLib dependencies compile files('lib/jar/cpcore.jar') @@ -29,7 +29,7 @@ dependencies { } // Antlr dependency - antlr 'org.antlr:antlr4:4.7.1' + antlr 'org.antlr:antlr4:4.7.2' } // Ensures that the lib/jar folder exists for downloading cpcore.jar @@ -83,6 +83,7 @@ jar { // Dynamically build run configurations for configured classes gradle.ext.drivers.each { name, className -> + tasks.register("run$name") task "run$name" (type: JavaExec, dependsOn: jar, overwrite: true) { description "Runs the ${name}.kt main class" group "KoebeLib" From 8051c0e52ac51a3f96e1a7770b4e8cc2f164276a Mon Sep 17 00:00:00 2001 From: browermb Date: Fri, 8 Feb 2019 11:29:25 -0500 Subject: [PATCH 23/24] added code for 3 disks to c-plane --- .../construction/BasicAlgorithmsS2.kt | 10 ++ src/gui/ConstructionGUI.kt | 6 + src/sketches/ConstructionSketch.kt | 141 ++++++++++++++++++ 3 files changed, 157 insertions(+) diff --git a/src/geometry/construction/BasicAlgorithmsS2.kt b/src/geometry/construction/BasicAlgorithmsS2.kt index 014c583..0635529 100644 --- a/src/geometry/construction/BasicAlgorithmsS2.kt +++ b/src/geometry/construction/BasicAlgorithmsS2.kt @@ -93,6 +93,16 @@ class TwoDisksPointCoaxialCircle() : IAlgorithm { } } +//class TwoDisksIntersectionLine() : IAlgorithm { +// override fun run(node: ConstructionNode): LineOP3 { +// if (node.incoming.size != 3) { +// throw InvalidConstructionParametersException("TwoDisksPointHyperbolicCircle expects two DiskS2s and one PointS2. ${node.incoming.size} given.") +// } +// +// return LineOP3(0.0, 0.0, 0.0, 0.0) +// } +//} + class TwoDisksIntersectionPoint() : IAlgorithm> { override fun run(node: ConstructionNode>): List { if (node.incoming.size < 2) { diff --git a/src/gui/ConstructionGUI.kt b/src/gui/ConstructionGUI.kt index 02fb096..33e46d3 100644 --- a/src/gui/ConstructionGUI.kt +++ b/src/gui/ConstructionGUI.kt @@ -27,6 +27,7 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { val selectionButton : JButton val intersectButton : JButton val disksPointCoaxialDisk: JButton + val threeDiskCPlane : JButton init { // Build the GUI: @@ -46,6 +47,7 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { selectionButton = JButton("Select") intersectButton = JButton("Intersection") disksPointCoaxialDisk = JButton("CoaxialFamilyDisk") + threeDiskCPlane = JButton("3DiskCPlane") buttonFlowPanel.add(arcballButton) buttonFlowPanel.add(pointButton) @@ -80,6 +82,10 @@ class ConstructionGUI(val sketch : ConstructionSketch) : JFrame() { disksPointCoaxialDisk.addActionListener { sketch.currentTool = CoaxialPointTool(sketch) } + + threeDiskCPlane.addActionListener { + sketch.currentTool = ThreeDiskCPlaneTool(sketch); + } } } diff --git a/src/sketches/ConstructionSketch.kt b/src/sketches/ConstructionSketch.kt index fcaf037..086f7d9 100644 --- a/src/sketches/ConstructionSketch.kt +++ b/src/sketches/ConstructionSketch.kt @@ -721,6 +721,147 @@ open class CoaxialPointTool(val sketch: ConstructionSketch) : MouseTool() { } } +open class ThreeDiskCPlaneTool(val sketch: ConstructionSketch) : MouseTool() { + var selectedNode : INode<*>? = null; + var selectedNodes = mutableListOf>() + + fun transform(mouseX: Int, mouseY: Int): PointE3 { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + + var l = PointE3.O - new1 + + var tca = l.dot(direction) + var d = (Math.sqrt(l.normSq() - tca * tca))//(200.0*zoom) + var thc = Math.sqrt(1 - d * d) + var t0 = tca - thc + var t1 = tca + thc + var inter = PointE3(0.0, 0.0, 0.0) + if (t0 > t1) { + inter = new1 + direction * t1 + return inter + } else { + inter = new1 + direction * t0 + return inter + } + } + return PointE3() + } + + fun isIntersection(mouseX : Int, mouseY : Int, a : Double, b : Double, c : Double, d : Double) : Boolean { + val gl = sketch.g + if (gl is PGraphicsOpenGL) { + var Minv = PMatrix3D(gl.projmodelview) + Minv.invert() //PVM inverted + var mousex = (2.0f * mouseX) / sketch.width - 1.0f + var mousey = 1.0f - (2.0f * mouseY) / sketch.height + + var w1 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m33 + var w2 = Minv.m30 * mousex + Minv.m31 * mousey + Minv.m32 + Minv.m33 + + var new1 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m03) / w1).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m13) / w1).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m23) / w1).toDouble() + ) + + var new2 = PointE3( + ((Minv.m00 * mousex + Minv.m01 * mousey + Minv.m02 + Minv.m03) / w2).toDouble(), + ((Minv.m10 * mousex + Minv.m11 * mousey + Minv.m12 + Minv.m13) / w2).toDouble(), + ((Minv.m20 * mousex + Minv.m21 * mousey + Minv.m22 + Minv.m23) / w2).toDouble() + ) + + var direction = (new2 - new1).normalize() + var rayOrigin = VectorE3(new1.x, new1.y, new1.z) + var worldOrigin = VectorE3(0.0, 0.0, 0.0) + var normalVector = VectorE3(a, b, c) + var denom = direction.dot(normalVector) + var t = ((worldOrigin - rayOrigin).dot(normalVector)) / denom + return t >= 0 + } + + return false; + } + + override fun mouseMoved(mouseX: Int, mouseY: Int) { + super.mouseMoved(mouseX, mouseY) + } + + override fun mouseDragged(mouseX: Int, mouseY: Int) { + + } + + override fun mousePressed(mouseX: Int, mouseY: Int) { + super.mousePressed(mouseX, mouseY) + val cursor = transform(mouseX, mouseY) + if (cursor != null) { + var minDist = 100.0 + for (node in sketch.construction.nodes) { + if (node != null) { + val output = node.getOutput() + if (output is DiskS2) { + val a = output.a + val b = output.b + val c = output.c + val d = output.d + if(isIntersection(mouseX, mouseY, a, b, c, d)) { + val center = output.centerE3 + val radius = output.radiusE3 + val diskDist = Math.sqrt(Math.pow(center.x - cursor.x, 2.0) + Math.pow(center.y - cursor.y, 2.0) + + Math.pow(center.z - cursor.z, 2.0)) - radius + if (diskDist < minDist) { + minDist = diskDist + selectedNode = node + } + } + } + } + } + + selectedNode?.style = Style(Color(200.0.toFloat(), 0.0f, 0.0f), Color(255.0.toFloat(), 0.0.toFloat(), 0.0.toFloat())) + if(!selectedNodes.contains(selectedNode)) { + selectedNodes.add(selectedNode as INode<*>) + } + } + } + + override fun mouseReleased(mouseX: Int, mouseY: Int) { + super.mouseReleased(mouseX, mouseY) + if (selectedNodes.size >= 3) { + var obj1 = selectedNodes[0] + var obj2 = selectedNodes[1] + var obj3 = selectedNodes[2] + + @Suppress("UNCHECKED_CAST") + var node = sketch.construction.makeCPlaneS2( obj1 as INode, + obj2 as INode, + obj3 as INode) + + } + } +} + open class ConstructionSketch : SphericalSketch() { var currentTool : MouseTool? = null; From 0807e602587700d7c7f6f6f9d8993a23dfe12994 Mon Sep 17 00:00:00 2001 From: Quincy Mast Date: Sat, 23 Feb 2019 08:38:21 -0500 Subject: [PATCH 24/24] upgrade gradle wrapper version --- gradle/wrapper/gradle-wrapper.jar | Bin 54413 -> 55190 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1948b9074f1016d15d505d185bc3f73deb82d8c8..87b738cbd051603d91cc39de6cb000dd98fe6b02 100644 GIT binary patch literal 55190 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 z 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