Category talk:Wren-ellipse: Difference between revisions

→‎Source code: Infrastructure changes to enable ellipses and circles to be treated as buttons and to make it easier to track button clicks.
(Added source code for new 'Wren-ellipse' module.)
 
(→‎Source code: Infrastructure changes to enable ellipses and circles to be treated as buttons and to make it easier to track button clicks.)
Line 5:
import "graphics" for Canvas, Color
import "math" for Math, Point
import "./polygon" for Selectable, Polygon, Rectangle, Square
 
/* Ellipse represents an ellipse in 2 dimensional space. */
class Ellipse is Selectable {
// Constructs a new Ellipse object with center (cx, cy),
// horizontal radius rx and vertical radius ry.
construct new(cx, cy, rx, ry, tag) {
if (!((cx is Num) && (cy is Num) && (rx is Num) && (ry is Num))) {
Fiber.abort("All arguments must be numbers.")
Line 19:
_rx = rx
_ry = ry
_tag = tag
}
 
// Convenience version of constructor for objects with an empty tag.
static new(cx, cy, rx, ry) { new(cx, cy, rx, ry, "") }
 
// Properties
Line 26 ⟶ 30:
rx { _rx }
ry { _ry }
 
tag { _tag }
tag=(t) { _tag = t }
selected { _selected }
selected=(s) { _selected = s }
 
center { Point.new(_cx, _cy) }
Line 163 ⟶ 173:
drawSectorfill(fillColor, startAngle, endAngle)
drawSector(borderColor, startAngle, endAngle)
}
 
// Returns whether a sector of the current instance contains a point (x, y).
// Points on the boundary are considered to be contained by the sector.
sectorContains(startAngle, endAngle, x, y) {
if (!contains(x, y)) return false
var rp = ((x - _cx) * (x - _cx) + (y - _cy) * (y - _cy)).sqrt
var theta = ((x - _cx) / rp).acos * 180 / Num.pi
return startAngle <= theta && endAngle >= theta
}
 
Line 192 ⟶ 211:
class Circle is Ellipse {
// Constructs a new Circle object with center (x, y) and radius r.
construct new(cx, cy, r, tag) {
super(cx, cy, r, r, tag)
_r = r
}
 
// Convenience version of constructor for objects with an empty tag.
static new(cx, cy, r) { new(cx, cy, r, "") }
 
// Properties
Line 230 ⟶ 252:
 
/* Button represents a rectangle with curved corners in 2 dimensional space. */
class Button is Selectable {
// Constructs a new elliptical Button object with center (x, y), width w and height h.
construct new(cx, cy, w, h, tag) {
if (!((cx is Num) && (cy is Num) && (w is Num) && (h is Num))) {
Fiber.abort("AllFirst four arguments must be numbers.")
}
_cx = cx
Line 240 ⟶ 262:
_w = w
_h = h
_tag = tag
}
 
// Convenience method which constructs a square button object with center (x, y) and widthside ws.
static newsquare(cx, cy, ws, tag) { new(cx, cy, ws, s, wtag) }
 
// Convenience versions of the above constructors for objects with an empty tag.
static new(cx, cy, w, h) { new(cx, cy, w, h, "") }
static square(cx, cy, s) { new(cx, cy, s, s, "") }
 
// Properties
Line 250 ⟶ 278:
width { _w }
height { _h }
 
tag { _tag }
tag=(t) { _tag = t }
selected { _selected }
selected=(s) { _selected = s }
 
// Draws the current instance in a given color.
Line 292 ⟶ 326:
var sy = Math.sin(a) * ry + e.cy
Canvas.line(sx, sy, sx + lineIncs[i][0], sy + lineIncs[i][1], borderColor, 2)
CanvasRectangle.rectfillnew(sx + rectIncs[i][0], sy + rectIncs[i][1], rx, ry, ).drawfill(fillColor)
}
// Canvas.rectfill(cx, cy, rx, ry, fillColor)
Rectangle.new(cx, cy, rx, ry).drawfill(fillColor)
}
 
// Convenience version of drawfill method where the fill and border colors are the same.
drawfill(c) { drawfill(c, c) }
 
// Returns whether the current instance contains a point (x, y).
// Points on the boundary are considered to be contained by the button.
contains(x, y) {
var rx = _w / 3
var ry = _h / 3
var cx = _cx - rx/2
var cy = _cy - ry/2
var angles = [[0, 90], [90, 180], [180, 270], [270, 360]]
var angles2 = [[0, 90], [90, 180], [90, 180], [0, 90]]
var centIncs = [[ rx, ry], [0, ry], [0, 0], [rx, 0]]
var lineIncs = [[-rx, 0], [0, -ry], [rx, 0], [0, ry]]
var rectIncs = [[-rx, -ry], [0, -ry], [0, 0], [-rx, 0]]
for (i in 0..3) {
var e = Ellipse.new(cx + centIncs[i][0], cy + centIncs[i][1], rx, ry)
var startAngle = angles2[i][0]
var endAngle = angles2[i][1]
if (e.sectorContains(startAngle, endAngle, x, y)) return true
startAngle = angles[i][0]
endAngle = angles[i][1]
var a = endAngle * Num.pi / 180
var sx = Math.cos(a) * rx + e.cx
var sy = Math.sin(a) * ry + e.cy
var rect = Rectangle.new(sx + rectIncs[i][0], sy + rectIncs[i][1], rx, ry)
if (rect.contains(x, y)) return true
}
if (Rectangle.new(cx, cy, rx, ry).contains(x, y)) return true
return false
}
}</lang>
9,476

edits