Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
kurs_java_alx_20240321
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Patryk Czarnik
kurs_java_alx_20240321
Commits
fc139742
Commit
fc139742
authored
Apr 10, 2024
by
Patryk Czarnik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Turtle
parent
35e31a58
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
2679 additions
and
0 deletions
+2679
-0
PierwszeProbyRysowania.java
src/turtle/PierwszeProbyRysowania.java
+20
-0
Turtle.java
src/turtle/Turtle.java
+2659
-0
No files found.
src/turtle/PierwszeProbyRysowania.java
0 → 100644
View file @
fc139742
package
turtle
;
import
java.awt.Color
;
public
class
PierwszeProbyRysowania
{
public
static
void
main
(
String
[]
args
)
{
Turtle
.
setCanvasSize
(
1200
,
900
);
Turtle
turtle
=
new
Turtle
();
turtle
.
forward
(
200
);
turtle
.
right
(
45
);
turtle
.
forward
(
100
);
turtle
.
penColor
(
Color
.
BLUE
);
turtle
.
width
(
3
);
turtle
.
right
(
90
);
turtle
.
forward
(
100
);
}
}
src/turtle/Turtle.java
0 → 100644
View file @
fc139742
package
turtle
;
/**AUTHOR: NICHOLAS SEWARD
* EMAIL: nicholas.seward@gmail.com
* LICENSE: MIT (USE THIS HOWEVER YOU SEE FIT.)
* DATE: 6/21/2012
* VERSION: 2 (THIS SHOULD BE VERSION 0.1 BUT THAT IS A SILLY NUMBERING SYSTEM.)
*
* https://github.com/NicholasSeward/Turtle
*
* THIS SOFTWARE HAS NO WARRANTY. IF IT WORKS, SUPER. IF IT DOESN'T, LET ME
* KNOW AND I MIGHT OR MIGHT NOT DO SOMETHING ABOUT IT.
*
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
import
java.awt.event.*
;
import
javax.swing.*
;
import
java.awt.*
;
import
java.awt.geom.*
;
import
java.awt.image.*
;
import
java.io.*
;
import
java.lang.reflect.Method
;
import
java.util.*
;
import
javax.imageio.ImageIO
;
import
javax.swing.filechooser.FileNameExtensionFilter
;
/**
* Turtle is a selfcontained class that will allow students to make
* beautiful turtle graphics with ease.
*
* @author Nicholas Seward
*/
@SuppressWarnings
(
"unchecked"
)
public
class
Turtle
implements
Runnable
,
ActionListener
,
MouseListener
,
MouseMotionListener
,
KeyListener
,
ComponentListener
,
MouseWheelListener
{
private
static
ArrayList
<
Turtle
>
turtles
;
private
static
TreeMap
<
Long
,
ArrayList
>
turtleStates
;
private
static
TreeMap
<
Long
,
ArrayList
>
redoStates
;
private
static
JFrame
window
;
private
static
JApplet
applet
;
private
static
JLabel
draw
;
private
static
int
width
,
height
;
private
static
BufferedImage
offscreenImage
,
midscreenImage
,
onscreenImage
;
private
static
Graphics2D
offscreen
,
midscreen
,
onscreen
;
private
static
BufferedImage
backgroundImage
;
private
static
Color
backgroundColor
;
private
static
ImageIcon
icon
;
private
static
Turtle
turtle
;
private
static
HashMap
<
String
,
Polygon
>
shapes
;
//You can only add. Never remove.
private
static
HashMap
<
String
,
Color
>
colors
;
private
static
HashMap
<
String
,
ArrayList
<
ArrayList
>>
keyBindings
;
private
static
HashMap
<
Turtle
,
ArrayList
<
ArrayList
>>
mouseBindings
;
private
static
double
centerX
,
centerY
;
private
static
double
scale
;
private
static
TreeSet
<
String
>
keysDown
;
private
static
TreeSet
<
String
>
processedKeys
;
private
static
TreeSet
<
String
>
unprocessedKeys
;
private
static
long
lastUpdate
;
private
static
long
fps
;
private
static
final
Object
turtleLock
=
new
Object
();
private
static
int
dragx
=
0
,
dragy
=
0
,
x
=
0
,
y
=
0
,
modifiers
=
0
;
private
static
final
Object
keyLock
=
new
Object
();
private
static
final
int
REFRESH_MODE_ANIMATED
=
0
;
private
static
final
int
REFRESH_MODE_STATE_CHANGE
=
1
;
private
static
final
int
REFRESH_MODE_ON_DEMAND
=
2
;
private
static
int
refreshMode
;
private
static
final
int
BACKGROUND_MODE_STRETCH
=
0
;
private
static
final
int
BACKGROUND_MODE_CENTER
=
1
;
private
static
final
int
BACKGROUND_MODE_TILE
=
2
;
private
static
final
int
BACKGROUND_MODE_CENTER_RELATIVE
=
3
;
private
static
final
int
BACKGROUND_MODE_TILE_RELATIVE
=
4
;
private
static
int
backgroundMode
;
private
static
Turtle
selectedTurtle
;
private
static
boolean
running
;
static
{
init
();
}
/**
* This is an internal method that should never be called.
*/
public
void
run
()
{
if
(
Thread
.
currentThread
().
getName
().
equals
(
"render"
))
renderLoop
();
else
if
(
Thread
.
currentThread
().
getName
().
equals
(
"listen"
))
eventLoop
();
}
private
void
eventLoop
()
{
//System.out.println("EVENT LOOP STARTED");
long
time
=
0
;
while
(
running
)
{
time
=
System
.
nanoTime
();
processKeys
();
waitUntil
(
time
+
1000000000
/
fps
);
}
}
private
void
renderLoop
()
{
//System.out.println("RENDER LOOP STARTED");
long
time
=
0
;
while
(
running
)
{
time
=
System
.
nanoTime
();
//System.out.println(time);
if
(
refreshMode
==
REFRESH_MODE_ANIMATED
)
draw
();
if
(!
waitUntil
(
time
+
1000000000
/
fps
))
fps
--;
else
if
(
fps
<
30
)
fps
++;
}
}
private
static
boolean
waitUntil
(
Long
time
)
{
long
now
=
System
.
nanoTime
();
if
(
now
<
time
)
{
try
{
Thread
.
sleep
((
time
-
now
)
/
1000000
);}
catch
(
Exception
e
)
{}
return
true
;
}
else
return
false
;
}
private
static
void
init
()
{
//mouseBindings.put(null, new ArrayList<ArrayList>());
turtles
=
new
ArrayList
<
Turtle
>();
turtleStates
=
new
TreeMap
<
Long
,
ArrayList
>();
redoStates
=
new
TreeMap
<
Long
,
ArrayList
>();
width
=
500
;
height
=
500
;
backgroundColor
=
Color
.
WHITE
;
keyBindings
=
new
HashMap
<
String
,
ArrayList
<
ArrayList
>>();
mouseBindings
=
new
HashMap
<
Turtle
,
ArrayList
<
ArrayList
>>();
centerX
=
0
;
centerY
=
0
;
scale
=
1
;
keysDown
=
new
TreeSet
<
String
>();
processedKeys
=
new
TreeSet
<
String
>();
unprocessedKeys
=
new
TreeSet
<
String
>();
lastUpdate
=
0
;
fps
=
30
;
dragx
=
0
;
dragy
=
0
;
x
=
0
;
y
=
0
;
modifiers
=
0
;
refreshMode
=
REFRESH_MODE_ANIMATED
;
backgroundMode
=
BACKGROUND_MODE_TILE_RELATIVE
;
selectedTurtle
=
null
;
running
=
true
;
window
=
new
JFrame
(
"Turtle"
);
icon
=
new
ImageIcon
();
setupBuffering
();
draw
=
new
JLabel
(
icon
);
window
.
setContentPane
(
draw
);
//window.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
try
{
window
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);}
catch
(
Exception
e
){}
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
"Save..."
);
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
window
.
setJMenuBar
(
menuBar
);
window
.
pack
();
window
.
requestFocusInWindow
();
drawTurtleIcon
();
window
.
setVisible
(
true
);
makeShapes
();
turtle
=
new
Turtle
(
0
);
draw
.
setFocusable
(
true
);
menuItem1
.
addActionListener
(
turtle
);
window
.
addComponentListener
(
turtle
);
draw
.
addComponentListener
(
turtle
);
draw
.
addMouseListener
(
turtle
);
draw
.
addMouseMotionListener
(
turtle
);
draw
.
addMouseWheelListener
(
turtle
);
window
.
addKeyListener
(
turtle
);
draw
.
addKeyListener
(
turtle
);
draw
.
requestFocus
();
initColors
();
// GraphicsEnvironment ge;
// ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
// String[] fontNames = ge.getAvailableFontFamilyNames();
// System.out.println(Arrays.toString(fontNames));
(
new
Thread
(
turtle
,
"render"
)).
start
();
(
new
Thread
(
turtle
,
"listen"
)).
start
();
}
public
static
void
exit
()
{
running
=
false
;
window
.
setVisible
(
false
);
window
.
dispose
();
}
/**
* This is an experimental method that should allow you to make turtle
* applets in the future. For now, it doesn't work because the key and
* mouse bindings require reflection and applets think that allowing
* reflection would open a security hole. Theoretically in the init method
* of the applet you need to place <code>Turtle.startApplet(this);</code>.
* <b>This is not currently working.</b>
*
* @param applet
*/
public
static
void
startApplet
(
JApplet
applet
)
{
//turtleStates.clear();
//turtles.clear();
//init();
Turtle
.
applet
=
applet
;
applet
.
setContentPane
(
window
.
getContentPane
());
window
.
setVisible
(
false
);
try
{(
new
Thread
((
Runnable
)
applet
,
"turtle"
)).
start
();}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
private
static
void
initColors
()
{
colors
=
new
HashMap
<
String
,
Color
>();
colors
.
put
(
"aliceblue"
,
new
Color
(
0xf0f8ff
));
colors
.
put
(
"antiquewhite"
,
new
Color
(
0xfaebd7
));
colors
.
put
(
"aqua"
,
new
Color
(
0x00ffff
));
colors
.
put
(
"aquamarine"
,
new
Color
(
0x7fffd4
));
colors
.
put
(
"azure"
,
new
Color
(
0xf0ffff
));
colors
.
put
(
"beige"
,
new
Color
(
0xf5f5dc
));
colors
.
put
(
"bisque"
,
new
Color
(
0xffe4c4
));
colors
.
put
(
"black"
,
new
Color
(
0x000000
));
colors
.
put
(
"blanchedalmond"
,
new
Color
(
0xffebcd
));
colors
.
put
(
"blue"
,
new
Color
(
0x0000ff
));
colors
.
put
(
"blueviolet"
,
new
Color
(
0x8a2be2
));
colors
.
put
(
"brown"
,
new
Color
(
0xa52a2a
));
colors
.
put
(
"burlywood"
,
new
Color
(
0xdeb887
));
colors
.
put
(
"cadetblue"
,
new
Color
(
0x5f9ea0
));
colors
.
put
(
"chartreuse"
,
new
Color
(
0x7fff00
));
colors
.
put
(
"chocolate"
,
new
Color
(
0xd2691e
));
colors
.
put
(
"coral"
,
new
Color
(
0xff7f50
));
colors
.
put
(
"cornflowerblue"
,
new
Color
(
0x6495ed
));
colors
.
put
(
"cornsilk"
,
new
Color
(
0xfff8dc
));
colors
.
put
(
"crimson"
,
new
Color
(
0xdc143c
));
colors
.
put
(
"cyan"
,
new
Color
(
0x00ffff
));
colors
.
put
(
"darkblue"
,
new
Color
(
0x00008b
));
colors
.
put
(
"darkcyan"
,
new
Color
(
0x008b8b
));
colors
.
put
(
"darkgoldenrod"
,
new
Color
(
0xb8860b
));
colors
.
put
(
"darkgray"
,
new
Color
(
0xa9a9a9
));
colors
.
put
(
"darkgreen"
,
new
Color
(
0x006400
));
colors
.
put
(
"darkkhaki"
,
new
Color
(
0xbdb76b
));
colors
.
put
(
"darkmagenta"
,
new
Color
(
0x8b008b
));
colors
.
put
(
"darkolivegreen"
,
new
Color
(
0x556b2f
));
colors
.
put
(
"darkorange"
,
new
Color
(
0xff8c00
));
colors
.
put
(
"darkorchid"
,
new
Color
(
0x9932cc
));
colors
.
put
(
"darkred"
,
new
Color
(
0x8b0000
));
colors
.
put
(
"darksalmon"
,
new
Color
(
0xe9967a
));
colors
.
put
(
"darkseagreen"
,
new
Color
(
0x8fbc8f
));
colors
.
put
(
"darkslateblue"
,
new
Color
(
0x483d8b
));
colors
.
put
(
"darkslategray"
,
new
Color
(
0x2f4f4f
));
colors
.
put
(
"darkturquoise"
,
new
Color
(
0x00ced1
));
colors
.
put
(
"darkviolet"
,
new
Color
(
0x9400d3
));
colors
.
put
(
"deeppink"
,
new
Color
(
0xff1493
));
colors
.
put
(
"deepskyblue"
,
new
Color
(
0x00bfff
));
colors
.
put
(
"dimgray"
,
new
Color
(
0x696969
));
colors
.
put
(
"dodgerblue"
,
new
Color
(
0x1e90ff
));
colors
.
put
(
"firebrick"
,
new
Color
(
0xb22222
));
colors
.
put
(
"floralwhite"
,
new
Color
(
0xfffaf0
));
colors
.
put
(
"forestgreen"
,
new
Color
(
0x228b22
));
colors
.
put
(
"fuchsia"
,
new
Color
(
0xff00ff
));
colors
.
put
(
"gainsboro"
,
new
Color
(
0xdcdcdc
));
colors
.
put
(
"ghostwhite"
,
new
Color
(
0xf8f8ff
));
colors
.
put
(
"gold"
,
new
Color
(
0xffd700
));
colors
.
put
(
"goldenrod"
,
new
Color
(
0xdaa520
));
colors
.
put
(
"gray"
,
new
Color
(
0x808080
));
colors
.
put
(
"green"
,
new
Color
(
0x008000
));
colors
.
put
(
"greenyellow"
,
new
Color
(
0xadff2f
));
colors
.
put
(
"honeydew"
,
new
Color
(
0xf0fff0
));
colors
.
put
(
"hotpink"
,
new
Color
(
0xff69b4
));
colors
.
put
(
"indianred"
,
new
Color
(
0xcd5c5c
));
colors
.
put
(
"indigo"
,
new
Color
(
0x4b0082
));
colors
.
put
(
"ivory"
,
new
Color
(
0xfffff0
));
colors
.
put
(
"khaki"
,
new
Color
(
0xf0e68c
));
colors
.
put
(
"lavender"
,
new
Color
(
0xe6e6fa
));
colors
.
put
(
"lavenderblush"
,
new
Color
(
0xfff0f5
));
colors
.
put
(
"lawngreen"
,
new
Color
(
0x7cfc00
));
colors
.
put
(
"lemonchiffon"
,
new
Color
(
0xfffacd
));
colors
.
put
(
"lightblue"
,
new
Color
(
0xadd8e6
));
colors
.
put
(
"lightcoral"
,
new
Color
(
0xf08080
));
colors
.
put
(
"lightcyan"
,
new
Color
(
0xe0ffff
));
colors
.
put
(
"lightgoldenrodyellow"
,
new
Color
(
0xfafad2
));
colors
.
put
(
"lightgreen"
,
new
Color
(
0x90ee90
));
colors
.
put
(
"lightgrey"
,
new
Color
(
0xd3d3d3
));
colors
.
put
(
"lightpink"
,
new
Color
(
0xffb6c1
));
colors
.
put
(
"lightsalmon"
,
new
Color
(
0xffa07a
));
colors
.
put
(
"lightseagreen"
,
new
Color
(
0x20b2aa
));
colors
.
put
(
"lightskyblue"
,
new
Color
(
0x87cefa
));
colors
.
put
(
"lightslategray"
,
new
Color
(
0x778899
));
colors
.
put
(
"lightsteelblue"
,
new
Color
(
0xb0c4de
));
colors
.
put
(
"lightyellow"
,
new
Color
(
0xffffe0
));
colors
.
put
(
"lime"
,
new
Color
(
0x00ff00
));
colors
.
put
(
"limegreen"
,
new
Color
(
0x32cd32
));
colors
.
put
(
"linen"
,
new
Color
(
0xfaf0e6
));
colors
.
put
(
"magenta"
,
new
Color
(
0xff00ff
));
colors
.
put
(
"maroon"
,
new
Color
(
0x800000
));
colors
.
put
(
"mediumaquamarine"
,
new
Color
(
0x66cdaa
));
colors
.
put
(
"mediumblue"
,
new
Color
(
0x0000cd
));
colors
.
put
(
"mediumorchid"
,
new
Color
(
0xba55d3
));
colors
.
put
(
"mediumpurple"
,
new
Color
(
0x9370db
));
colors
.
put
(
"mediumseagreen"
,
new
Color
(
0x3cb371
));
colors
.
put
(
"mediumslateblue"
,
new
Color
(
0x7b68ee
));
colors
.
put
(
"mediumspringgreen"
,
new
Color
(
0x00fa9a
));
colors
.
put
(
"mediumturquoise"
,
new
Color
(
0x48d1cc
));
colors
.
put
(
"mediumvioletred"
,
new
Color
(
0xc71585
));
colors
.
put
(
"midnightblue"
,
new
Color
(
0x191970
));
colors
.
put
(
"mintcream"
,
new
Color
(
0xf5fffa
));
colors
.
put
(
"mistyrose"
,
new
Color
(
0xffe4e1
));
colors
.
put
(
"moccasin"
,
new
Color
(
0xffe4b5
));
colors
.
put
(
"navajowhite"
,
new
Color
(
0xffdead
));
colors
.
put
(
"navy"
,
new
Color
(
0x000080
));
colors
.
put
(
"oldlace"
,
new
Color
(
0xfdf5e6
));
colors
.
put
(
"olive"
,
new
Color
(
0x808000
));
colors
.
put
(
"olivedrab"
,
new
Color
(
0x6b8e23
));
colors
.
put
(
"orange"
,
new
Color
(
0xffa500
));
colors
.
put
(
"orangered"
,
new
Color
(
0xff4500
));
colors
.
put
(
"orchid"
,
new
Color
(
0xda70d6
));
colors
.
put
(
"palegoldenrod"
,
new
Color
(
0xeee8aa
));
colors
.
put
(
"palegreen"
,
new
Color
(
0x98fb98
));
colors
.
put
(
"paleturquoise"
,
new
Color
(
0xafeeee
));
colors
.
put
(
"palevioletred"
,
new
Color
(
0xdb7093
));
colors
.
put
(
"papayawhip"
,
new
Color
(
0xffefd5
));
colors
.
put
(
"peachpuff"
,
new
Color
(
0xffdab9
));
colors
.
put
(
"peru"
,
new
Color
(
0xcd853f
));
colors
.
put
(
"pink"
,
new
Color
(
0xffc0cb
));
colors
.
put
(
"plum"
,
new
Color
(
0xdda0dd
));
colors
.
put
(
"powderblue"
,
new
Color
(
0xb0e0e6
));
colors
.
put
(
"purple"
,
new
Color
(
0x800080
));
colors
.
put
(
"red"
,
new
Color
(
0xff0000
));
colors
.
put
(
"rosybrown"
,
new
Color
(
0xbc8f8f
));
colors
.
put
(
"royalblue"
,
new
Color
(
0x4169e1
));
colors
.
put
(
"saddlebrown"
,
new
Color
(
0x8b4513
));
colors
.
put
(
"salmon"
,
new
Color
(
0xfa8072
));
colors
.
put
(
"sandybrown"
,
new
Color
(
0xf4a460
));
colors
.
put
(
"seagreen"
,
new
Color
(
0x2e8b57
));
colors
.
put
(
"seashell"
,
new
Color
(
0xfff5ee
));
colors
.
put
(
"sienna"
,
new
Color
(
0xa0522d
));
colors
.
put
(
"silver"
,
new
Color
(
0xc0c0c0
));
colors
.
put
(
"skyblue"
,
new
Color
(
0x87ceeb
));
colors
.
put
(
"slateblue"
,
new
Color
(
0x6a5acd
));
colors
.
put
(
"slategray"
,
new
Color
(
0x708090
));
colors
.
put
(
"snow"
,
new
Color
(
0xfffafa
));
colors
.
put
(
"springgreen"
,
new
Color
(
0x00ff7f
));
colors
.
put
(
"steelblue"
,
new
Color
(
0x4682b4
));
colors
.
put
(
"tan"
,
new
Color
(
0xd2b48c
));
colors
.
put
(
"teal"
,
new
Color
(
0x008080
));
colors
.
put
(
"thistle"
,
new
Color
(
0xd8bfd8
));
colors
.
put
(
"tomato"
,
new
Color
(
0xff6347
));
colors
.
put
(
"turquoise"
,
new
Color
(
0x40e0d0
));
colors
.
put
(
"violet"
,
new
Color
(
0xee82ee
));
colors
.
put
(
"wheat"
,
new
Color
(
0xf5deb3
));
colors
.
put
(
"white"
,
new
Color
(
0xffffff
));
colors
.
put
(
"whitesmoke"
,
new
Color
(
0xf5f5f5
));
colors
.
put
(
"yellow"
,
new
Color
(
0xffff00
));
colors
.
put
(
"yellowgreen"
,
new
Color
(
0x9acd32
));
}
private
static
Color
getColor
(
String
color
)
{
String
origColor
=
color
;
color
=
color
.
toLowerCase
().
replaceAll
(
"[^a-z]"
,
""
);
if
(
colors
.
containsKey
(
color
))
{
return
colors
.
get
(
color
);
}
else
{
return
null
;
}
}
private
static
void
setupBuffering
()
{
synchronized
(
turtleLock
)
{
lastUpdate
=
0
;
offscreenImage
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_ARGB
);
midscreenImage
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_ARGB
);
onscreenImage
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_ARGB
);
offscreen
=
offscreenImage
.
createGraphics
();
midscreen
=
midscreenImage
.
createGraphics
();
onscreen
=
onscreenImage
.
createGraphics
();
//offscreen.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
//offscreen.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
offscreen
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
midscreen
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
onscreen
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
drawBackground
(
offscreen
);
drawBackground
(
onscreen
);
icon
.
setImage
(
onscreenImage
);
}
}
private
static
void
drawTurtleIcon
()
{
byte
[]
imageData
=
new
byte
[]{
71
,
73
,
70
,
56
,
57
,
97
,
16
,
0
,
16
,
0
,-
95
,
2
,
0
,
0
,-
103
,
0
,
0
,-
1
,
0
,-
1
,-
1
,-
1
,-
1
,-
1
,-
1
,
33
,-
7
,
4
,
1
,
10
,
0
,
2
,
0
,
44
,
0
,
0
,
0
,
0
,
16
,
0
,
16
,
0
,
0
,
2
,
44
,-
108
,-
113
,-
87
,-
53
,-
19
,-
33
,-
128
,
4
,
104
,
74
,
35
,
67
,-
72
,
34
,-
21
,
11
,
124
,
27
,-
90
,-
107
,-
109
,
72
,
117
,-
91
,-
71
,
110
,
103
,-
37
,
90
,-
31
,-
10
,-
55
,-
87
,
122
,-
34
,
74
,
72
,-
15
,
17
,-
56
,-
127
,
8
,
33
,
5
,
0
,
59
};
try
{
BufferedImage
tmpicon
=
ImageIO
.
read
(
new
ByteArrayInputStream
(
imageData
));
window
.
setIconImage
(
tmpicon
);
}
catch
(
Exception
e
)
{}
}
private
static
void
makeShapes
()
{
shapes
=
new
HashMap
<
String
,
Polygon
>();
int
[]
xs
=
new
int
[]{
66
,
65
,
63
,
61
,
53
,
44
,
33
,
24
,
23
,
19
,
17
,
14
,
9
,
8
,
8
,
10
,
13
,
11
,
10
,
2
,
9
,
11
,
15
,
11
,
11
,
10
,
12
,
18
,
20
,
22
,
23
,
26
,
35
,
44
,
53
,
61
,
62
,
64
,
66
,
71
,
77
,
78
,
77
,
76
,
72
,
77
,
81
,
86
,
91
,
94
,
97
,
98
,
97
,
95
,
92
,
87
,
82
,
77
,
72
,
74
,
77
,
78
,
76
,
70
};
int
[]
ys
=
new
int
[]{
18
,
19
,
21
,
25
,
23
,
22
,
23
,
27
,
25
,
21
,
20
,
21
,
27
,
30
,
32
,
34
,
37
,
42
,
47
,
50
,
53
,
59
,
65
,
68
,
69
,
71
,
74
,
79
,
80
,
80
,
78
,
74
,
77
,
78
,
77
,
75
,
79
,
81
,
82
,
81
,
76
,
73
,
71
,
69
,
66
,
59
,
60
,
61
,
60
,
58
,
54
,
50
,
46
,
42
,
40
,
39
,
40
,
41
,
34
,
32
,
28
,
27
,
24
,
19
};
Polygon
p
=
new
Polygon
(
xs
,
ys
,
xs
.
length
);
shapes
.
put
(
"turtle"
,
p
);
xs
=
new
int
[]{
0
,
100
,
0
,
20
};
ys
=
new
int
[]{
0
,
50
,
100
,
50
};
p
=
new
Polygon
(
xs
,
ys
,
xs
.
length
);
shapes
.
put
(
"arrow"
,
p
);
xs
=
new
int
[]{
0
,
100
,
100
,
0
};
ys
=
new
int
[]{
0
,
0
,
100
,
100
};
p
=
new
Polygon
(
xs
,
ys
,
xs
.
length
);
shapes
.
put
(
"rectangle"
,
p
);
shapes
.
put
(
"square"
,
p
);
xs
=
new
int
[]{
0
,
100
,
0
};
ys
=
new
int
[]{
0
,
50
,
100
};
p
=
new
Polygon
(
xs
,
ys
,
xs
.
length
);
shapes
.
put
(
"triangle"
,
p
);
int
divisions
=
24
;
xs
=
new
int
[
divisions
];
ys
=
new
int
[
divisions
];
for
(
int
i
=
0
;
i
<
divisions
;
i
++)
{
double
angle
=
Math
.
toRadians
(
i
*
360.0
/
divisions
);
xs
[
i
]=(
int
)
Math
.
round
(
50
+
50
*
Math
.
cos
(
angle
));
ys
[
i
]=(
int
)
Math
.
round
(
50
+
50
*
Math
.
sin
(
angle
));
}
p
=
new
Polygon
(
xs
,
ys
,
xs
.
length
);
shapes
.
put
(
"circle"
,
p
);
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ TURTLE CONSTRUCTION_/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
/**
* This is a internal constuctor that makes a singleton that does the
* listening but is not added to the stack of turtles to be rendered.
* You don't need to use this outside of the Turtle.java file.
*
* @param i Pass this any integer. It doesn't do anything.
*/
private
Turtle
(
int
i
){}
private
Point2D
.
Double
location
=
new
Point2D
.
Double
(
0
,
0
);
private
double
direction
=
0
;
//degrees
private
String
shape
=
"turtle"
;
//Stores a key to the shapes hashmap
private
BufferedImage
image
=
null
;
private
double
shapeWidth
=
33
;
private
double
shapeHeight
=
33
;
private
double
tilt
=
0
;
private
double
penWidth
=
2
;
private
Color
penColor
=
Color
.
BLACK
;
private
double
outlineWidth
=
2
;
private
Color
outlineColor
=
Color
.
BLACK
;
private
Color
fillColor
=
new
Color
(
0
,
255
,
0
,
128
);
private
double
speed
=
50
;
//milliseconds to execute a move
private
boolean
isPenDown
=
true
;
private
boolean
isFilling
=
false
;
private
boolean
isVisible
=
true
;
private
ArrayList
<
Point2D
.
Double
>
polygon
=
new
ArrayList
<
Point2D
.
Double
>();
//temporary storage
private
Long
_time
;
private
Point2D
.
Double
_location
;
private
Double
_direction
;
private
String
_shape
;
private
BufferedImage
_image
;
private
Double
_shapeWidth
;
private
Double
_shapeHeight
;
private
Double
_tilt
;
private
Double
_penWidth
;
private
Color
_penColor
;
private
Double
_outlineWidth
;
private
Color
_outlineColor
;
private
Color
_fillColor
;
private
Double
_speed
;
private
Boolean
_isPenDown
;
private
Boolean
_isFilling
;
private
Boolean
_isVisible
;
private
ArrayList
<
Point2D
.
Double
>
_polygon
;
private
Boolean
_isFill
;
private
Boolean
_isStamp
;
private
Double
_dotSize
;
private
Color
_dotColor
;
private
Font
_font
;
private
String
_text
;
private
Integer
_justification
;
private
Point2D
.
Double
_textOffset
;
//secondary temporary storage
private
Long
__time
;
private
Point2D
.
Double
__location
;
private
Double
__direction
;
private
String
__shape
;
private
BufferedImage
__image
;
private
Double
__shapeWidth
;
private
Double
__shapeHeight
;
private
Double
__tilt
;
private
Double
__penWidth
;
private
Color
__penColor
;
private
Double
__outlineWidth
;
private
Color
__outlineColor
;
private
Color
__fillColor
;
private
Double
__speed
;
private
Boolean
__isPenDown
;
private
Boolean
__isFilling
;
private
Boolean
__isVisible
;
private
ArrayList
<
Point2D
.
Double
>
__polygon
;
private
Boolean
__isFill
;
private
Boolean
__isStamp
;
private
Double
__dotSize
;
private
Color
__dotColor
;
private
Font
__font
;
private
String
__text
;
private
Integer
__justification
;
private
Point2D
.
Double
__textOffset
;
/**
* Makes a default turtle.
*/
public
Turtle
()
{
if
(
window
==
null
)
init
();
synchronized
(
turtleLock
){
turtles
.
add
(
this
);}
long
time
=
storeCurrentState
();
updateAll
();
}
/**
* Makes a default turtle at the specified position.
*
* @param x x coordinate
* @param y y coordinate
*/
public
Turtle
(
double
x
,
double
y
)
{
if
(
window
==
null
)
init
();
location
=
new
Point2D
.
Double
(
x
,
y
);
synchronized
(
turtleLock
){
turtles
.
add
(
this
);}
long
time
=
storeCurrentState
();
updateAll
();
}
/**
* This creates a cloned copy of a turtle.
*
* @return a cloned copy of a turtle
*/
public
Turtle
clone
()
{
Turtle
t
=
new
Turtle
(
0
);
t
.
location
=(
Point2D
.
Double
)
this
.
location
.
clone
();
t
.
direction
=
this
.
direction
;
t
.
shape
=
t
.
shape
;
t
.
image
=
this
.
image
;
t
.
shapeWidth
=
this
.
shapeWidth
;
t
.
shapeHeight
=
this
.
shapeHeight
;
t
.
tilt
=
this
.
tilt
;
t
.
penWidth
=
this
.
penWidth
;
t
.
penColor
=
this
.
penColor
;
t
.
outlineWidth
=
this
.
outlineWidth
;
t
.
outlineColor
=
this
.
outlineColor
;
t
.
fillColor
=
this
.
fillColor
;
t
.
speed
=
this
.
speed
;
t
.
isPenDown
=
this
.
isPenDown
;
t
.
isFilling
=
this
.
isFilling
;
t
.
isVisible
=
this
.
isVisible
;
if
(
window
==
null
)
init
();
synchronized
(
turtleLock
){
turtles
.
add
(
t
);}
long
time
=
t
.
storeCurrentState
();
return
t
;
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ STATE MANAGEMENT _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
private
long
storeCurrentState
()
{
return
storeCurrentState
(
false
,
false
,
0
,
null
,
null
,
null
,
0
,
null
);
}
private
long
storeAnimatedState
()
{
return
storeCurrentState
(
true
,
false
,
0
,
null
,
null
,
null
,
0
,
null
);
}
private
long
storeCurrentState
(
boolean
animate
,
boolean
isStamp
,
double
dotSize
,
Color
dotColor
,
Font
font
,
String
text
,
int
justification
,
Point2D
.
Double
textOffset
)
{
ArrayList
state
=
new
ArrayList
();
long
time
=
System
.
nanoTime
();
synchronized
(
turtleLock
)
{
state
.
add
(
0
);
//0
state
.
add
(
this
);
//1
state
.
add
(
location
.
clone
());
//2
state
.
add
(
direction
);
//3
state
.
add
(
shape
);
//4
state
.
add
(
image
);
//5
state
.
add
(
shapeWidth
);
//6
state
.
add
(
shapeHeight
);
//7
state
.
add
(
tilt
);
//8
state
.
add
(
penWidth
);
//9
state
.
add
(
penColor
);
//10
state
.
add
(
outlineWidth
);
//11
state
.
add
(
outlineColor
);
//12
state
.
add
(
fillColor
);
//13
state
.
add
(
speed
);
//14
state
.
add
(
isPenDown
);
//15
state
.
add
(
isFilling
);
//16
state
.
add
(
isVisible
);
//17
state
.
add
(
isStamp
);
//18
state
.
add
(
dotSize
);
//19
state
.
add
(
dotColor
);
//20
state
.
add
(
font
);
//21
state
.
add
(
text
);
//22
state
.
add
(
justification
);
//23
state
.
add
(
textOffset
);
//24
if
(!
turtleStates
.
isEmpty
()
&&
turtleStates
.
lastKey
()>
time
)
time
=
turtleStates
.
lastKey
()+
1
;
if
(
animate
)
time
+=(
long
)(
speed
*
1000000
);
state
.
set
(
0
,
time
);
turtleStates
.
put
(
time
,
state
);
redoStates
.
clear
();
}
if
(
refreshMode
==
REFRESH_MODE_STATE_CHANGE
)
draw
();
if
(
refreshMode
==
REFRESH_MODE_ANIMATED
)
waitUntil
(
time
);
return
time
;
}
private
static
void
clearStorage
()
{
synchronized
(
turtleLock
)
{
for
(
Turtle
t:
turtles
)
{
t
.
__time
=
null
;
t
.
__location
=
null
;
t
.
__direction
=
null
;
t
.
__shape
=
null
;
t
.
__image
=
null
;
t
.
__shapeWidth
=
null
;
t
.
__shapeHeight
=
null
;
t
.
__tilt
=
null
;
t
.
__penWidth
=
null
;
t
.
__penColor
=
null
;
t
.
__outlineWidth
=
null
;
t
.
__outlineColor
=
null
;
t
.
__fillColor
=
null
;
t
.
__speed
=
null
;
t
.
__isPenDown
=
null
;
t
.
__isFilling
=
null
;
t
.
__isVisible
=
null
;
t
.
__isStamp
=
null
;
t
.
__dotSize
=
null
;
t
.
__dotColor
=
null
;
t
.
__font
=
null
;
t
.
__text
=
null
;
t
.
__justification
=
null
;
t
.
__textOffset
=
null
;
t
.
_time
=
null
;
t
.
_location
=
null
;
t
.
_direction
=
null
;
t
.
_shape
=
null
;
t
.
_shapeWidth
=
null
;
t
.
_shapeHeight
=
null
;
t
.
_image
=
null
;
t
.
_tilt
=
null
;
t
.
_penWidth
=
null
;
t
.
_penColor
=
null
;
t
.
_outlineWidth
=
null
;
t
.
_outlineColor
=
null
;
t
.
_fillColor
=
null
;
t
.
_speed
=
null
;
t
.
_isPenDown
=
null
;
t
.
_isFilling
=
null
;
t
.
_isVisible
=
null
;
t
.
_isStamp
=
null
;
t
.
_dotSize
=
null
;
t
.
_dotColor
=
null
;
t
.
_font
=
null
;
t
.
_text
=
null
;
t
.
_justification
=
null
;
t
.
_textOffset
=
null
;
}
}
}
private
static
void
retrieveState
(
long
time
)
{
synchronized
(
turtleLock
)
{
Turtle
t
=
getStateTurtle
(
turtleStates
.
get
(
time
));
t
.
__time
=
t
.
_time
;
t
.
__location
=
t
.
_location
;
t
.
__direction
=
t
.
_direction
;
t
.
__shape
=
t
.
_shape
;
t
.
__image
=
t
.
_image
;
t
.
__shapeWidth
=
t
.
_shapeWidth
;
t
.
__shapeHeight
=
t
.
_shapeHeight
;
t
.
__tilt
=
t
.
_tilt
;
t
.
__penWidth
=
t
.
_penWidth
;
t
.
__penColor
=
t
.
_penColor
;
t
.
__outlineWidth
=
t
.
_outlineWidth
;
t
.
__outlineColor
=
t
.
_outlineColor
;
t
.
__fillColor
=
t
.
_fillColor
;
t
.
__speed
=
t
.
_speed
;
t
.
__isPenDown
=
t
.
_isPenDown
;
t
.
__isFilling
=
t
.
_isFilling
;
t
.
__isVisible
=
t
.
_isVisible
;
t
.
__isStamp
=
t
.
_isStamp
;
t
.
__dotSize
=
t
.
_dotSize
;
t
.
__dotColor
=
t
.
_dotColor
;
t
.
__font
=
t
.
_font
;
t
.
__text
=
t
.
_text
;
t
.
__justification
=
t
.
_justification
;
t
.
__textOffset
=
t
.
_textOffset
;
ArrayList
state
=
turtleStates
.
get
(
time
);
t
.
_time
=
getStateTime
(
state
);
t
.
_location
=
getStateLocation
(
state
);
t
.
_direction
=
getStateDirection
(
state
);
t
.
_shape
=
getStateShape
(
state
);
t
.
_shapeWidth
=
getStateShapeWidth
(
state
);
t
.
_shapeHeight
=
getStateShapeHeight
(
state
);
t
.
_image
=
getStateImage
(
state
);
t
.
_tilt
=
getStateTilt
(
state
);
t
.
_penWidth
=
getStatePenWidth
(
state
);
t
.
_penColor
=
getStatePenColor
(
state
);
t
.
_outlineWidth
=
getStateOutlineWidth
(
state
);
t
.
_outlineColor
=
getStateOutlineColor
(
state
);
t
.
_fillColor
=
getStateFillColor
(
state
);
t
.
_speed
=
getStateSpeed
(
state
);
t
.
_isPenDown
=
getStateIsPenDown
(
state
);
t
.
_isFilling
=
getStateIsFilling
(
state
);
t
.
_isVisible
=
getStateIsVisible
(
state
);
t
.
_isStamp
=
getStateIsStamp
(
state
);
t
.
_dotSize
=
getStateDotSize
(
state
);
t
.
_dotColor
=
getStateDotColor
(
state
);
t
.
_font
=
getStateFont
(
state
);
t
.
_text
=
getStateText
(
state
);
t
.
_justification
=
getStateJustification
(
state
);
t
.
_textOffset
=
getStateTextOffset
(
state
);
}
}
private
static
long
getStateTime
(
ArrayList
state
){
return
(
Long
)
state
.
get
(
0
);}
private
static
Turtle
getStateTurtle
(
ArrayList
state
){
return
(
Turtle
)
state
.
get
(
1
);}
private
static
Point2D
.
Double
getStateLocation
(
ArrayList
state
){
return
(
Point2D
.
Double
)((
Point2D
.
Double
)
state
.
get
(
2
)).
clone
();}
private
static
double
getStateDirection
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
3
);}
private
static
String
getStateShape
(
ArrayList
state
){
return
(
String
)
state
.
get
(
4
);}
private
static
BufferedImage
getStateImage
(
ArrayList
state
){
return
(
BufferedImage
)
state
.
get
(
5
);}
private
static
double
getStateShapeWidth
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
6
);}
private
static
double
getStateShapeHeight
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
7
);}
private
static
double
getStateTilt
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
8
);}
private
static
double
getStatePenWidth
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
9
);}
private
static
Color
getStatePenColor
(
ArrayList
state
){
return
(
Color
)
state
.
get
(
10
);}
private
static
double
getStateOutlineWidth
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
11
);}
private
static
Color
getStateOutlineColor
(
ArrayList
state
){
return
(
Color
)
state
.
get
(
12
);}
private
static
Color
getStateFillColor
(
ArrayList
state
){
return
(
Color
)
state
.
get
(
13
);}
private
static
double
getStateSpeed
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
14
);}
private
static
boolean
getStateIsPenDown
(
ArrayList
state
){
return
(
Boolean
)
state
.
get
(
15
);}
private
static
boolean
getStateIsFilling
(
ArrayList
state
){
return
(
Boolean
)
state
.
get
(
16
);}
private
static
boolean
getStateIsVisible
(
ArrayList
state
){
return
(
Boolean
)
state
.
get
(
17
);}
private
static
boolean
getStateIsStamp
(
ArrayList
state
){
return
(
Boolean
)
state
.
get
(
18
);}
private
static
double
getStateDotSize
(
ArrayList
state
){
return
(
Double
)
state
.
get
(
19
);}
private
static
Color
getStateDotColor
(
ArrayList
state
){
return
(
Color
)
state
.
get
(
20
);}
private
static
Font
getStateFont
(
ArrayList
state
){
return
(
Font
)
state
.
get
(
21
);}
private
static
String
getStateText
(
ArrayList
state
){
return
(
String
)
state
.
get
(
22
);}
private
static
int
getStateJustification
(
ArrayList
state
){
return
(
Integer
)
state
.
get
(
23
);}
private
static
Point2D
.
Double
getStateTextOffset
(
ArrayList
state
){
return
(
Point2D
.
Double
)
state
.
get
(
24
);}
private
static
void
restoreState
(
long
time
)
{
ArrayList
state
=
turtleStates
.
get
(
time
);
Turtle
t
=
getStateTurtle
(
turtleStates
.
get
(
time
));
t
.
location
=
getStateLocation
(
state
);
t
.
direction
=
getStateDirection
(
state
);
t
.
shape
=
getStateShape
(
state
);
t
.
shapeWidth
=
getStateShapeWidth
(
state
);
t
.
shapeHeight
=
getStateShapeHeight
(
state
);
t
.
image
=
getStateImage
(
state
);
t
.
tilt
=
getStateTilt
(
state
);
t
.
penWidth
=
getStatePenWidth
(
state
);
t
.
penColor
=
getStatePenColor
(
state
);
t
.
outlineWidth
=
getStateOutlineWidth
(
state
);
t
.
outlineColor
=
getStateOutlineColor
(
state
);
t
.
fillColor
=
getStateFillColor
(
state
);
t
.
speed
=
getStateSpeed
(
state
);
t
.
isPenDown
=
getStateIsPenDown
(
state
);
t
.
isFilling
=
getStateIsFilling
(
state
);
t
.
isVisible
=
getStateIsVisible
(
state
);
if
(
refreshMode
==
REFRESH_MODE_STATE_CHANGE
)
draw
();
}
private
void
select
()
{
selectedTurtle
=
this
;
}
private
void
unselect
()
{
if
(
selectedTurtle
==
this
)
selectedTurtle
=
null
;
}
/**
* Determines if a turtle is covering a screen position
*
* @param x x screen coordinate
* @param y y screen coordinate
* @return true if this turtle is at the indicated screen position.
*/
public
boolean
contains
(
int
x
,
int
y
)
{
Point2D
.
Double
point
=
new
Point2D
.
Double
(
x
,
y
);
if
(
_location
==
null
)
return
false
;
AffineTransform
m
=
offscreen
.
getTransform
();
double
x1
,
y1
,
dir1
;
x1
=
_location
.
x
;
y1
=
_location
.
y
;
dir1
=
_direction
;
m
.
translate
(((
x1
-
centerX
)*
scale
+
width
/
2
),((
y1
-
centerY
)*(-
scale
)+
height
/
2
));
m
.
scale
(
scale
,
scale
);
if
(
image
==
null
)
{
m
.
rotate
(-
Math
.
toRadians
(
dir1
));
m
.
scale
(
shapeWidth
/
100.0
,
shapeHeight
/
100.0
);
m
.
translate
(-
50
,-
50
);
Polygon
p
=
shapes
.
get
(
shape
);
GeneralPath
gp
=
new
GeneralPath
();
gp
.
append
(
p
.
getPathIterator
(
m
),
false
);
return
gp
.
contains
(
x
,
y
);
}
else
{
int
w
=
image
.
getWidth
();
int
h
=
image
.
getHeight
();
m
.
rotate
(-
Math
.
toRadians
(
dir1
));
m
.
scale
(
shapeWidth
/
1.0
/
w
,
shapeHeight
/
1.0
/
h
);
m
.
translate
(-
w
/
2
,-
h
/
2
);
try
{
m
.
inverseTransform
(
point
,
point
);}
catch
(
Exception
e
){
return
false
;}
x
=(
int
)
point
.
x
;
y
=(
int
)
point
.
y
;
try
{
//System.out.println((new Color(image.getRGB(x, y),true)).getAlpha());
return
(
new
Color
(
image
.
getRGB
(
x
,
y
),
true
)).
getAlpha
()>
50
;
}
catch
(
Exception
e
){
return
false
;}
}
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ TURTLE METHODS _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
/**
* Gets the speed of the animation.
* @return milliseconds it takes to do one action
*/
public
double
getSpeed
()
{
return
speed
;
}
/**
* Sets the speed of the animation.
* @param delay milliseconds it takes to do one action
* @return state change timestamp
*/
public
long
speed
(
double
delay
)
{
this
.
speed
=
delay
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Moves the turtle forward by the distance.
*
* @param distance distance to move forward
* @return state change timestamp
*/
public
long
forward
(
double
distance
)
{
double
angle
=
Math
.
toRadians
(
direction
);
Point2D
.
Double
pastLocation
=(
Point2D
.
Double
)
location
.
clone
();
location
.
x
+=
distance
*
Math
.
cos
(
angle
);
location
.
y
+=
distance
*
Math
.
sin
(
angle
);
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Moves the turtle backward by the distance.
*
* @param distance distance to move backward
* @return state change timestamp
*/
public
long
backward
(
double
distance
)
{
double
angle
=
Math
.
toRadians
(
direction
);
Point2D
.
Double
pastLocation
=(
Point2D
.
Double
)
location
.
clone
();
location
.
x
-=
distance
*
Math
.
cos
(
angle
);
location
.
y
-=
distance
*
Math
.
sin
(
angle
);
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Turns the turtle left by the number of indicated degrees.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public
long
left
(
double
angle
)
{
direction
+=
angle
;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Turns the turtle right by the number of indicated degrees.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public
long
right
(
double
angle
)
{
direction
-=
angle
;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Gets the direction the turtle is facing neglecting tilt.
*
* @return state change timestamp
*/
public
double
getDirection
()
{
double
a
=
direction
;
while
(
a
>=
360
)
a
-=
360
;
while
(
a
<
0
)
a
+=
360
;
return
a
;
}
/**
* Sets the direction the turtle is facing neglecting tilt.
*
* @param direction angle counter-clockwise from east
* @return state change timestamp
*/
public
long
setDirection
(
double
direction
)
{
double
a
=
direction
;
while
(
this
.
direction
-
a
>
180
)
a
+=
360
;
while
(
this
.
direction
-
a
<-
180
)
a
-=
360
;
this
.
direction
=
a
;
//this.direction=direction;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Moves the turtle to (0,0) and facing east.
*
* @return state change timestamp
*/
public
long
home
()
{
return
setPosition
(
0
,
0
,
0
);
}
/**
* Hides the turtle but it can still draw.
*
* @return state change timestamp
*/
public
long
hide
()
{
isVisible
=
false
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Makes the turtle visible.
*
* @return state change timestamp
*/
public
long
show
()
{
isVisible
=
true
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the direction in such a way that it faces (x,y)
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return state change timestamp
*/
public
long
face
(
double
x
,
double
y
)
{
return
setDirection
(
towards
(
x
,
y
));
}
/**
* Gets direction towards (x,y)
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return angle in degrees where 0<=angle<360
*/
public
double
towards
(
double
x
,
double
y
)
{
return
Math
.
toDegrees
(
Math
.
atan2
(
y
-
location
.
y
,
x
-
location
.
x
));
}
/**
* Gets the distance to another position.
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return distance between turtle's current location and another position
*/
public
double
distance
(
double
x
,
double
y
)
{
return
Math
.
sqrt
((
y
-
location
.
y
)*(
y
-
location
.
y
)+(
x
-
location
.
x
)*(
x
-
location
.
x
));
}
/**
* Gets the x coordinate of the turtle.
*
* @return x coordinate
*/
public
double
getX
()
{
return
location
.
x
;
}
/**
* Gets the y coordinate of the turtle.
*
* @return y coordinate
*/
public
double
getY
()
{
return
location
.
y
;
}
/**
* Sets the position and direction of a turtle.
*
* @param x x coordinate
* @param y y coordinate
* @param direction angle counter-clockwise from east in degrees
* @return state change timestamp
*/
public
long
setPosition
(
double
x
,
double
y
,
double
direction
)
{
location
.
x
=
x
;
location
.
y
=
y
;
double
a
=
direction
;
while
(
this
.
direction
-
a
>
180
)
a
+=
360
;
while
(
this
.
direction
-
a
<-
180
)
a
-=
360
;
this
.
direction
=
a
;
this
.
direction
=
direction
;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Sets the position of a turtle.
*
* @param x x coordinate
* @param y y coordinate
* @return state change timestamp
*/
public
long
setPosition
(
double
x
,
double
y
)
{
return
setPosition
(
x
,
y
,
direction
);
}
/**
* Adds an additional angle to rotation of the turtle's shape when rendering.
* This is useful when you need to face a different direction than the
* direction you are moving in.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public
long
tilt
(
double
angle
)
{
tilt
+=
angle
;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Sets the angle to rotate the turtle's shape when rendering.
* This is useful when you need to face a different direction than the
* direction you are moving in.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public
long
setTilt
(
double
angle
)
{
//double a=angle;
//while(tilt-a>180)a+=360;
//while(tilt-a<-180)a-=360;
//tilt=a;
tilt
=
angle
;
long
timeStamp
=
storeAnimatedState
();
return
timeStamp
;
}
/**
* Gets the rotation of the turtle's shape away from the turtle's direction.
*
* @return tilt in degrees (positive in counter-clockwise)
*/
public
double
getTilt
()
{
return
tilt
;
}
/**
* Sets the width of the turtles path
*
* @param penWidth width of the turtles path
* @return state change timestamp
*/
public
long
width
(
double
penWidth
)
{
this
.
penWidth
=
penWidth
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the width of the turtle's outline.
*
* @param width width of the turtle's outline
* @return state change timestamp
*/
public
long
outlineWidth
(
double
width
)
{
this
.
outlineWidth
=
width
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Picks the turtle's tail up so it won't draw on the screen as it moves.
*
* @return state change timestamp
*/
public
long
up
()
{
this
.
isPenDown
=
false
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Puts the turtle's tail down so it will draw on the screen as it moves.
*
* @return state change timestamp
*/
public
long
down
()
{
this
.
isPenDown
=
true
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
public
long
stab
()
{
Color
c
=
Turtle
.
getColor
(
"red"
);
if
(
c
!=
null
)
this
.
penColor
=
c
;
this
.
isPenDown
=
true
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's path color.
*
* @param penColor Color of the turtle's path.
* @return state change timestamp
*/
public
long
penColor
(
String
penColor
)
{
Color
c
=
Turtle
.
getColor
(
penColor
);
if
(
c
!=
null
)
this
.
penColor
=
c
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's path color.
*
* @param penColor Color of the turtle's path.
* @return state change timestamp
*/
public
long
penColor
(
Color
penColor
)
{
this
.
penColor
=
penColor
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's outlineColor color.
*
* @param outlineColor Color of the turtle's outlineColor.
* @return state change timestamp
*/
public
long
outlineColor
(
String
outlineColor
)
{
Color
c
=
Turtle
.
getColor
(
outlineColor
);
if
(
c
!=
null
)
this
.
outlineColor
=
c
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's outlineColor color.
*
* @param outlineColor Color of the turtle's outlineColor.
* @return state change timestamp
*/
public
long
outlineColor
(
Color
outlineColor
)
{
this
.
outlineColor
=
outlineColor
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's fill color.
*
* @param fillColor Color of the turtle's fill.
* @return state change timestamp
*/
public
long
fillColor
(
String
fillColor
)
{
Color
c
=
Turtle
.
getColor
(
fillColor
);
if
(
c
!=
null
)
this
.
fillColor
=
c
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the turtle's fill color.
*
* @param fillColor Color of the turtle's fill.
* @return state change timestamp
*/
public
long
fillColor
(
Color
fillColor
)
{
this
.
fillColor
=
fillColor
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Sets the shape of the turtle using the built in shapes (turtle,square,
* rectangle,triangle,arrow,circle) or to a image.
*
* @param shape shapename or filename of image
* @return state change timestamp
*/
public
long
shape
(
String
shape
)
{
try
{
image
=
ImageIO
.
read
(
new
File
(
shape
));
this
.
shapeHeight
=
image
.
getHeight
();
this
.
shapeWidth
=
image
.
getWidth
();
}
catch
(
Exception
e
)
{
if
(
shapes
.
containsKey
(
shape
))
{
this
.
shape
=
shape
;
this
.
shapeHeight
=
33
;
this
.
shapeWidth
=
33
;
image
=
null
;
}
else
{
System
.
out
.
println
(
"Unrecognized filename or shape name."
);}
}
//if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
public
long
shapeSize
(
int
width
,
int
height
)
{
this
.
shapeHeight
=
height
;
this
.
shapeWidth
=
width
;
long
timeStamp
=
storeCurrentState
();
return
timeStamp
;
}
/**
* Put a copy of the current turtle shape on the canvas.
*
* @return state change timestamp
*/
public
long
stamp
()
{
long
timeStamp
=
storeCurrentState
(
true
,
true
,
0
,
null
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @return state change timestamp
*/
public
long
dot
()
{
long
timeStamp
=
storeCurrentState
(
true
,
false
,
penWidth
*
3
,
penColor
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @param color color of dot
* @return state change timestamp
*/
public
long
dot
(
String
color
)
{
Color
c
=
Turtle
.
getColor
(
color
);
if
(
c
==
null
)
c
=
penColor
;
long
timeStamp
=
storeCurrentState
(
true
,
false
,
penWidth
*
3
,
c
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @param color color of dot
* @return state change timestamp
*/
public
long
dot
(
Color
color
)
{
long
timeStamp
=
storeCurrentState
(
true
,
false
,
penWidth
*
3
,
color
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
/**
* Put a dot on the canvas.
*
* @param color color of dot
* @param dotSize diameter of the dot
* @return state change timestamp
*/
public
long
dot
(
String
color
,
double
dotSize
)
{
Color
c
=
Turtle
.
getColor
(
color
);
if
(
c
==
null
)
c
=
penColor
;
long
timeStamp
=
storeCurrentState
(
true
,
false
,
dotSize
,
c
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
/**
* Put a dot on the canvas.
*
* @param color color of dot
* @param dotSize diameter of the dot
* @return state change timestamp
*/
public
long
dot
(
Color
color
,
double
dotSize
)
{
long
timeStamp
=
storeCurrentState
(
true
,
false
,
dotSize
,
color
,
null
,
null
,
0
,
null
);
return
timeStamp
;
}
public
long
write
(
String
text
,
String
fontName
,
int
fontSize
,
int
justification
,
double
xOffset
,
double
yOffset
)
{
return
0
;
}
/**
* Undo turtle state changes.
*
* @param steps the number of state changes to remove
*/
public
void
undo
(
int
steps
)
{
for
(
int
i
=
0
;
i
<
steps
;
i
++)
rollback
();
lastUpdate
=
0
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Undo the last turtle state change.
*/
public
void
undo
()
{
rollback
();
lastUpdate
=
0
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Redo turtle state changes.
*
* @param steps the number of state changes to restore
*/
public
void
redo
(
int
steps
)
{
for
(
int
i
=
0
;
i
<
steps
;
i
++)
rollforward
();
lastUpdate
=
0
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Redo turtle state changes.
*/
public
void
redo
()
{
rollforward
();
lastUpdate
=
0
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Clears all the drawing that a turtle has done but all the turtle
* settings remain the same. (color, location, direction, shape)
*/
public
void
clear
()
{
synchronized
(
turtleLock
)
{
long
removeKey
=
0
;
TreeMap
<
Long
,
ArrayList
>
copy_turtleStates
=(
TreeMap
<
Long
,
ArrayList
>)
turtleStates
.
clone
();
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry:
copy_turtleStates
.
entrySet
())
{
ArrayList
state
=
entry
.
getValue
();
long
time
=
entry
.
getKey
();
if
(
getStateTurtle
(
state
)==
this
)
{
if
(
removeKey
!=
0
)
{
turtleStates
.
remove
(
removeKey
);
}
removeKey
=
time
;
}
}
redoStates
.
clear
();
restoreState
(
removeKey
);
}
lastUpdate
=
0
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
private
void
rollback
()
{
int
steps
=
0
;
synchronized
(
turtleLock
)
{
long
removeKey
=
0
;
long
restoreTime
=
0
;
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry:
turtleStates
.
descendingMap
().
entrySet
())
{
ArrayList
state
=
entry
.
getValue
();
long
time
=
entry
.
getKey
();
if
(
getStateTurtle
(
state
)==
this
)
{
if
(
steps
==
0
)
{
removeKey
=
time
;
steps
+=
1
;
}
else
{
restoreTime
=
time
;
break
;
}
}
}
if
(
removeKey
!=
0
&&
restoreTime
!=
0
)
{
restoreState
(
restoreTime
);
redoStates
.
put
(
removeKey
,
turtleStates
.
remove
(
removeKey
));
}
}
}
private
void
rollforward
()
{
synchronized
(
turtleLock
)
{
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry:
redoStates
.
entrySet
())
{
ArrayList
state
=
entry
.
getValue
();
long
time
=
entry
.
getKey
();
if
(
getStateTurtle
(
state
)==
this
)
{
turtleStates
.
put
(
entry
.
getKey
(),
redoStates
.
remove
(
entry
.
getKey
()));
restoreState
(
time
);
return
;
}
}
}
}
/**
* This specifies when the screen gets refreshed.
* 0(default)=Animated (The turtle will slide from one state to another without being jerky.)
* 1=State Change (The turtle will refresh immediately to the last state. Jerky motion.)
* 2=On Demand (The turtle will refresh only when you call update())
*
* @param mode refresh mode
*/
public
static
void
refreshMode
(
int
mode
)
{
refreshMode
=
mode
;
updateAll
();
}
/**
* This specifies how the background is drawn.
* 0=The image if present is stretched to fill the screen.
* 1=The image is centered on the middle of the screen and will not scale/pan
* 2=The image is tiled and will not scale/pan
* 3=The image is centered on (0,0) and will scale/pan
* 4(default)=The image is tiled and will scale/pan
*
* @param mode background mode
*/
public
static
void
backgroundMode
(
int
mode
)
{
backgroundMode
=
mode
;
updateAll
();
}
/**
* Sets the background color.
*
* @param color Color of the background.
*/
public
static
void
bgcolor
(
String
color
)
{
Color
c
=
Turtle
.
getColor
(
color
);
if
(
c
!=
null
)
backgroundColor
=
c
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Sets the background color.
*
* @param color Color of the background.
*/
public
static
void
bgcolor
(
Color
color
)
{
backgroundColor
=
color
;
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
/**
* Set the background image.
*
* @param filename filename for a background image
*/
public
static
void
bgpic
(
String
filename
)
{
try
{
backgroundImage
=
ImageIO
.
read
(
new
File
(
filename
));}
catch
(
Exception
e
){
e
.
printStackTrace
();}
if
(
refreshMode
!=
REFRESH_MODE_ON_DEMAND
)
updateAll
();
}
private
static
boolean
addMouseBinding
(
String
methodName
,
Turtle
t
,
boolean
append
,
boolean
click
,
boolean
repeat
)
{
String
className
=
""
;
try
{
throw
new
Exception
(
"Who called me?"
);
}
catch
(
Exception
e
)
{
className
=
e
.
getStackTrace
()[
2
].
getClassName
();
}
try
{
boolean
works
=
false
;
for
(
Method
m
:
Class
.
forName
(
className
).
getDeclaredMethods
())
{
if
(
m
.
getName
().
equals
(
methodName
))
{
//System.out.println(m);
works
=
true
;
for
(
Class
paramType
:
m
.
getParameterTypes
())
{
//System.out.println(paramType.getName());
if
(!
paramType
.
getName
().
equals
(
"double"
)
&&
!
paramType
.
getName
().
equals
(
"java.lang.Double"
)
&&
!
paramType
.
getName
().
equals
(
"Turtle"
))
{
works
=
false
;
break
;
}
}
if
(
works
)
break
;
}
}
if
(
works
)
{
//System.out.println("Method found!");
}
else
{
System
.
out
.
println
(
"ERROR"
);
return
false
;
}
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"Calling Class not found."
);
return
false
;
}
if
(!
append
||
!
mouseBindings
.
containsKey
(
t
))
mouseBindings
.
put
(
t
,
new
ArrayList
<
ArrayList
>());
ArrayList
binding
=
new
ArrayList
();
binding
.
add
(
t
);
binding
.
add
(
className
);
binding
.
add
(
methodName
);
binding
.
add
(
click
);
binding
.
add
(
repeat
);
mouseBindings
.
get
(
t
).
add
(
binding
);
return
true
;
}
private
boolean
addKeyBinding
(
String
methodName
,
String
keyText
,
boolean
append
,
boolean
repeat
)
{
keyText
=
keyText
.
toLowerCase
();
String
className
=
""
;
try
{
throw
new
Exception
(
"Who called me?"
);
}
catch
(
Exception
e
)
{
className
=
e
.
getStackTrace
()[
2
].
getClassName
();
}
try
{
boolean
works
=
false
;
for
(
Method
m
:
Class
.
forName
(
className
).
getDeclaredMethods
())
{
if
(
m
.
getName
().
equals
(
methodName
))
{
//System.out.println(m);
works
=
true
;
for
(
Class
paramType
:
m
.
getParameterTypes
())
{
//System.out.println(paramType.getName());
if
(!
paramType
.
getName
().
equals
(
"java.lang.String"
)
&&
!
paramType
.
getName
().
equals
(
"Turtle"
))
{
works
=
false
;
break
;
}
}
if
(
works
)
break
;
}
}
if
(
works
)
{
//System.out.println("Method found!");
}
else
{
System
.
out
.
println
(
"ERROR"
);
return
false
;
}
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
"Calling Class not found."
);
return
false
;
}
if
(!
append
||
!
keyBindings
.
containsKey
(
keyText
))
keyBindings
.
put
(
keyText
,
new
ArrayList
<
ArrayList
>());
ArrayList
binding
=
new
ArrayList
();
binding
.
add
(
this
);
binding
.
add
(
className
);
binding
.
add
(
methodName
);
binding
.
add
(
repeat
);
keyBindings
.
get
(
keyText
).
add
(
binding
);
return
true
;
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @return
*/
public
boolean
onKey
(
String
methodName
,
String
keyText
)
{
return
addKeyBinding
(
methodName
,
keyText
,
false
,
false
);
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @param append true if you want to have multiple methods per key
* @return
*/
public
boolean
onKey
(
String
methodName
,
String
keyText
,
boolean
append
)
{
return
addKeyBinding
(
methodName
,
keyText
,
append
,
false
);
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @param append true if you want to have multiple methods per key
* @param repeat true if you want call the method every screen refresh
* @return
*/
public
boolean
onKey
(
String
methodName
,
String
keyText
,
boolean
append
,
boolean
repeat
)
{
return
addKeyBinding
(
methodName
,
keyText
,
append
,
repeat
);
}
/**
*
* Fits the indicated box in the center of the screen as large as possible.
*
* @param minx left x coordinate of box
* @param miny bottom y coordinate of box
* @param maxx right x coordinate of box
* @param maxy top y coordinate of box
*/
public
static
void
zoom
(
double
minx
,
double
miny
,
double
maxx
,
double
maxy
)
{
synchronized
(
turtleLock
)
{
centerX
=(
minx
+
maxx
)/
2
;
centerY
=(
miny
+
maxy
)/
2
;
if
(
width
/(
maxx
-
minx
)>
height
/(
maxy
-
miny
))
scale
=
height
/(
maxy
-
miny
);
else
scale
=
width
/(
maxx
-
minx
);
updateAll
();
}
}
/**
* Fits everything on the screen.
*/
public
static
void
zoomFit
()
{
synchronized
(
turtleLock
)
{
Point2D
.
Double
loc
;
if
(
turtleStates
.
isEmpty
())
return
;
else
loc
=
getStateLocation
(
turtleStates
.
firstEntry
().
getValue
());
double
minx
=
loc
.
x
,
miny
=
loc
.
y
;
double
maxx
=
minx
,
maxy
=
miny
;
double
shapeWidth
=
0
;
double
shapeHeight
=
0
;
long
time
=
System
.
nanoTime
();
if
(
refreshMode
!=
REFRESH_MODE_ANIMATED
)
time
=
turtleStates
.
lastKey
()+
1
;
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry
:
turtleStates
.
headMap
(
time
).
entrySet
())
{
ArrayList
state
=
entry
.
getValue
();
if
(!
getStateIsPenDown
(
state
))
continue
;
Point2D
.
Double
location
=
getStateLocation
(
state
);
if
(
location
.
x
<
minx
)
minx
=
location
.
x
;
if
(
location
.
x
>
maxx
)
maxx
=
location
.
x
;
if
(
location
.
y
<
miny
)
miny
=
location
.
y
;
if
(
location
.
y
>
maxy
)
maxy
=
location
.
y
;
shapeWidth
=
getStateShapeWidth
(
state
);
shapeHeight
=
getStateShapeHeight
(
state
);
}
if
(
turtleStates
.
lastKey
()>
time
&&
getStateSpeed
(
turtleStates
.
lastEntry
().
getValue
())>
0
)
{
double
percent
=
1
-
(
turtleStates
.
lastKey
()
-
time
)
/
getStateSpeed
(
turtleStates
.
lastEntry
().
getValue
())
/
1000000.0
;
//System.out.println("trying");
Turtle
t
=
getStateTurtle
(
turtleStates
.
lastEntry
().
getValue
());
double
x1
=
t
.
_location
.
x
,
y1
=
t
.
_location
.
y
,
x2
=
t
.
__location
.
x
,
y2
=
t
.
__location
.
y
;
x1
=(
x2
-
x1
)*
percent
+
x1
;
y1
=(
y2
-
y1
)*
percent
+
y1
;
if
(
x1
<
minx
)
minx
=
x1
;
if
(
x1
>
maxx
)
maxx
=
x1
;
if
(
y1
<
miny
)
miny
=
y1
;
if
(
y1
>
maxy
)
maxy
=
y1
;
}
double
shapeMax
=
Math
.
max
(
shapeWidth
,
shapeHeight
);
zoom
(
minx
-
shapeMax
/
2
,
miny
-
shapeMax
/
2
,
maxx
+
shapeMax
/
2
,
maxy
+
shapeMax
/
2
);
}
}
private
static
void
updateAll
()
{
lastUpdate
=
0
;
draw
();
}
/**
* Force redraw when the refreshMode is set to on demand.
*/
public
static
void
update
()
{
if
(
refreshMode
==
REFRESH_MODE_ON_DEMAND
)
draw
();
}
private
static
void
draw
()
{
synchronized
(
turtleLock
)
{
long
renderTime
=
System
.
nanoTime
();
if
(
turtleStates
.
isEmpty
()
||
lastUpdate
==
0
)
{
clearStorage
();
drawBackground
(
offscreen
);
}
if
(
turtleStates
.
isEmpty
())
{
onscreen
.
drawImage
(
offscreenImage
,
0
,
0
,
null
);
window
.
repaint
();
if
(
applet
!=
null
)
applet
.
repaint
();
return
;
}
if
(
refreshMode
!=
REFRESH_MODE_ANIMATED
)
renderTime
=
turtleStates
.
lastKey
()+
1
;
if
(
lastUpdate
>
turtleStates
.
lastKey
())
{
midscreen
.
drawImage
(
offscreenImage
,
0
,
0
,
null
);
for
(
Turtle
t:
turtles
)
{
if
(
t
.
isVisible
)
t
.
drawStamp
(
1
,
midscreen
);
//if(t==selectedTurtle)t.drawCrossHairs(1,midscreen);
}
onscreen
.
drawImage
(
midscreenImage
,
0
,
0
,
null
);
window
.
repaint
();
if
(
applet
!=
null
)
applet
.
repaint
();
return
;
}
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry
:
turtleStates
.
tailMap
(
lastUpdate
).
headMap
(
renderTime
).
entrySet
())
{
retrieveState
(
entry
.
getKey
());
Turtle
t
=
getStateTurtle
(
entry
.
getValue
());
t
.
drawLine
(
1
,
offscreen
);
if
(
t
.
_isStamp
)
t
.
drawStamp
(
1
,
offscreen
);
t
.
drawDot
(
1
,
offscreen
);
}
midscreen
.
drawImage
(
offscreenImage
,
0
,
0
,
null
);
Turtle
animatedTurtle
=
null
;
double
percent
=
1
;
Long
t2
;
t2
=
new
Long
(
0
);
if
(
renderTime
<
turtleStates
.
lastKey
())
{
animatedTurtle
=
getStateTurtle
(
turtleStates
.
ceilingEntry
(
renderTime
).
getValue
());
t2
=
animatedTurtle
.
_time
;
retrieveState
(
turtleStates
.
ceilingKey
(
renderTime
));
if
(
animatedTurtle
.
_speed
>
0
)
{
percent
=
1
-
(
turtleStates
.
ceilingKey
(
renderTime
)
-
renderTime
)
/
animatedTurtle
.
_speed
/
1000000.0
;
}
else
percent
=
1
;
if
(
percent
<
0
)
percent
=
0
;
}
for
(
Turtle
t:
turtles
)
{
if
(
t
==
animatedTurtle
)
{
//System.out.println(percent);
t
.
drawLine
(
percent
,
midscreen
);
if
(
t
.
_dotSize
>
0
)
t
.
drawDot
(
percent
,
midscreen
);
if
(
t
.
isVisible
)
t
.
drawStamp
(
percent
,
midscreen
,
false
);
if
(
t
.
_isStamp
)
t
.
drawStamp
(
percent
,
midscreen
,
true
);
//if(t==selectedTurtle)t.drawCrossHairs(percent,midscreen);
try
{
retrieveState
(
t2
);}
catch
(
Exception
e
){}
}
else
{
if
(
t
.
isVisible
)
t
.
drawStamp
(
1
,
midscreen
);
//if(t==selectedTurtle)t.drawCrossHairs(1,midscreen);
}
}
lastUpdate
=
renderTime
;
//zoomFit();
onscreen
.
drawImage
(
midscreenImage
,
0
,
0
,
null
);
window
.
repaint
();
if
(
applet
!=
null
)
applet
.
repaint
();
}
}
private
void
drawLine
(
double
percent
,
Graphics2D
g
)
{
if
(!
_isPenDown
)
return
;
g
.
setColor
(
_penColor
);
g
.
setStroke
(
new
BasicStroke
((
float
)(
scale
*
_penWidth
),
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
));
if
(
__location
!=
null
&&
!
__location
.
equals
(
_location
))
{
double
x1
=
_location
.
x
,
y1
=
_location
.
y
,
x2
=
__location
.
x
,
y2
=
__location
.
y
;
if
(
percent
<
1
&&
percent
>=
0
)
{
x1
=(
x1
-
x2
)*
percent
+
x2
;
y1
=(
y1
-
y2
)*
percent
+
y2
;
}
//g.draw(new Line2D.Double((x1-centerX)*scale+width/2, (y1-centerY)*(-scale)+height/2, (x2-centerX)*scale+width/2, (y2-centerY)*(-scale)+height/2));
g
.
drawLine
((
int
)((
x1
-
centerX
)*
scale
+
width
/
2
),
(
int
)((
y1
-
centerY
)*(-
scale
)+
height
/
2
),
(
int
)((
x2
-
centerX
)*
scale
+
width
/
2
),
(
int
)((
y2
-
centerY
)*(-
scale
)+
height
/
2
));
}
}
private
void
drawStamp
(
double
percent
,
Graphics2D
g
)
{
drawStamp
(
percent
,
g
,
false
);
}
private
void
drawStamp
(
double
percent
,
Graphics2D
g
,
boolean
isStamp
)
{
if
(
_location
==
null
)
return
;
AffineTransform
originalTransform
=(
AffineTransform
)
g
.
getTransform
().
clone
();
AffineTransform
m
=
g
.
getTransform
();
double
x1
,
x2
,
y1
,
y2
,
dir1
,
dir2
,
tilt1
,
tilt2
;
x1
=
_location
.
x
;
y1
=
_location
.
y
;
dir1
=
_direction
;
tilt1
=
_tilt
;
if
(
__location
==
null
)
{
x2
=
x1
;
y2
=
y1
;
dir2
=
dir1
;
tilt2
=
tilt1
;
}
else
{
x2
=
__location
.
x
;
y2
=
__location
.
y
;
dir2
=
__direction
;
tilt2
=
__tilt
;
}
if
(
percent
<
1
&&
percent
>=
0
)
{
x1
=(
x1
-
x2
)*
percent
+
x2
;
y1
=(
y1
-
y2
)*
percent
+
y2
;
dir1
=(
dir1
-
dir2
)*
percent
+
dir2
;
tilt1
=(
tilt1
-
tilt2
)*
percent
+
tilt2
;
}
m
.
translate
(((
x1
-
centerX
)*
scale
+
width
/
2
),((
y1
-
centerY
)*(-
scale
)+
height
/
2
));
if
(
isStamp
)
m
.
scale
(
scale
*
percent
,
scale
*
percent
);
else
m
.
scale
(
scale
,
scale
);
if
(
_image
==
null
)
{
//_outlineWidth=0.0;
m
.
rotate
(-
Math
.
toRadians
(
dir1
+
tilt1
));
m
.
scale
(
_shapeWidth
/
100.0
,
_shapeHeight
/
100.0
);
m
.
translate
(-
50
,-
50
);
g
.
setTransform
(
m
);
Polygon
p
=
shapes
.
get
(
_shape
);
g
.
setColor
(
_fillColor
);
g
.
fillPolygon
(
p
);
g
.
setColor
(
_outlineColor
);
if
(
_outlineWidth
>
0
)
{
g
.
setStroke
(
new
BasicStroke
((
float
)(
_outlineWidth
*
scale
),
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
));
g
.
setTransform
(
originalTransform
);
GeneralPath
gp
=
new
GeneralPath
();
gp
.
append
(
p
.
getPathIterator
(
m
),
false
);
g
.
draw
(
gp
);
}
}
else
{
int
w
=
_image
.
getWidth
();
int
h
=
_image
.
getHeight
();
m
.
rotate
(-
Math
.
toRadians
(
dir1
+
tilt1
));
m
.
scale
(
_shapeWidth
/
1.0
/
w
,
_shapeHeight
/
1.0
/
h
);
m
.
translate
(-
w
/
2
,-
h
/
2
);
g
.
setTransform
(
m
);
g
.
drawImage
(
_image
,
0
,
0
,
null
);
}
g
.
setTransform
(
originalTransform
);
}
private
void
drawDot
(
double
percent
,
Graphics2D
g
)
{
AffineTransform
originalTransform
=(
AffineTransform
)
g
.
getTransform
().
clone
();
AffineTransform
m
=
g
.
getTransform
();
m
.
translate
(((
_location
.
x
-
centerX
)*
scale
+
width
/
2
),((
_location
.
y
-
centerY
)*(-
scale
)+
height
/
2
));
m
.
scale
(
scale
*
percent
/
2
,
scale
*
percent
/
2
);
g
.
setTransform
(
m
);
g
.
setColor
(
_dotColor
);
int
r
=(
int
)(
_dotSize
*
1.0
);
g
.
fillOval
(-
r
,
-
r
,
2
*
r
,
2
*
r
);
g
.
setTransform
(
originalTransform
);
}
private
static
void
drawBackground
(
Graphics2D
g
)
{
g
.
setColor
(
backgroundColor
);
g
.
fillRect
(
0
,
0
,
width
,
height
);
if
(
backgroundImage
==
null
)
return
;
int
w
=
backgroundImage
.
getWidth
();
int
h
=
backgroundImage
.
getHeight
();
if
(
backgroundMode
==
BACKGROUND_MODE_CENTER
)
{
offscreen
.
drawImage
(
backgroundImage
,
(
width
-
w
)/
2
,
(
height
-
h
)/
2
,
w
,
h
,
null
);
}
else
if
(
backgroundMode
==
BACKGROUND_MODE_STRETCH
)
{
offscreen
.
drawImage
(
backgroundImage
,
0
,
0
,
width
,
height
,
null
);
}
else
if
(
backgroundMode
==
BACKGROUND_MODE_CENTER_RELATIVE
)
{
offscreen
.
drawImage
(
backgroundImage
,
(
int
)((-
w
/
2
-
centerX
)*
scale
+
width
/
2
),(
int
)((
h
/
2
-
centerY
)*(-
scale
)+
height
/
2
),
(
int
)(
w
*
scale
),
(
int
)(
h
*
scale
),
null
);
}
else
if
(
backgroundMode
==
BACKGROUND_MODE_TILE
)
{
for
(
int
i
=
0
;
i
<
width
;
i
+=
w
)
for
(
int
j
=
0
;
j
<
height
;
j
+=
h
)
offscreen
.
drawImage
(
backgroundImage
,
i
,
j
,
w
,
h
,
null
);
}
else
if
(
backgroundMode
==
BACKGROUND_MODE_TILE_RELATIVE
)
{
double
left
=
centerX
-
width
/
2
/
scale
;
double
top
=
centerY
+
height
/
2
/
scale
;
double
right
=
centerX
+
width
/
2
/
scale
;
double
bottom
=
centerY
-
height
/
2
/
scale
;
for
(
double
x
=((
int
)(
left
/
w
)-
1
)*
w
;
x
<=
right
;
x
+=
w
)
for
(
double
y
=((
int
)(
bottom
/
h
))*
h
;
y
<=
top
+
h
;
y
+=
h
)
offscreen
.
drawImage
(
backgroundImage
,
(
int
)((
x
-
centerX
)*
scale
+
width
/
2
),(
int
)((
y
-
centerY
)*(-
scale
)+
height
/
2
),
(
int
)
Math
.
ceil
(
w
*
scale
),
(
int
)
Math
.
ceil
(
h
*
scale
),
null
);
}
}
private
void
drawCrossHairs
(
double
percent
,
Graphics2D
g
)
{
if
(
_location
==
null
)
return
;
double
time
=(
System
.
nanoTime
()/
100000000
)/
10.0
;
AffineTransform
originalTransform
=(
AffineTransform
)
g
.
getTransform
().
clone
();
AffineTransform
m
=
g
.
getTransform
();
double
x1
,
x2
,
y1
,
y2
,
dir1
,
dir2
;
x1
=
_location
.
x
;
y1
=
_location
.
y
;
if
(
__location
==
null
)
{
x2
=
x1
;
y2
=
y1
;
}
else
{
x2
=
__location
.
x
;
y2
=
__location
.
y
;
}
if
(
percent
<
1
&&
percent
>=
0
)
{
x1
=(
x1
-
x2
)*
percent
+
x2
;
y1
=(
y1
-
y2
)*
percent
+
y2
;
}
m
.
translate
(((
x1
-
centerX
)*
scale
+
width
/
2
),((
y1
-
centerY
)*(-
scale
)+
height
/
2
));
int
f
=
10
;
m
.
scale
(
scale
/
f
,
scale
/
f
);
g
.
setTransform
(
m
);
int
period
=
50
;
int
r
=(
int
)(
Math
.
sqrt
(
shapeWidth
*
shapeWidth
+
shapeHeight
*
shapeHeight
)*
f
/
2
);
g
.
setColor
(
new
Color
(
255
,
255
,
255
));
g
.
setStroke
(
new
BasicStroke
((
float
)(
6
*
f
),
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
));
g
.
drawOval
(-
r
,
-
r
,
2
*
r
,
2
*
r
);
r
+=
f
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
g
.
drawLine
((
int
)(
r
*
Math
.
cos
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),(
int
)(
r
*
Math
.
sin
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),
(
int
)((
r
+
r
/
5
)*
Math
.
cos
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),(
int
)((
r
+
r
/
5
)*
Math
.
sin
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)));
r
-=
f
;
g
.
setColor
(
new
Color
(
0
,
0
,
0
));
g
.
setStroke
(
new
BasicStroke
((
float
)(
3
*
f
),
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
));
g
.
drawOval
(-
r
,
-
r
,
2
*
r
,
2
*
r
);
r
+=
f
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
g
.
drawLine
((
int
)(
r
*
Math
.
cos
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),(
int
)(
r
*
Math
.
sin
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),
(
int
)((
r
+
r
/
5
)*
Math
.
cos
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)),(
int
)((
r
+
r
/
5
)*
Math
.
sin
(
Math
.
PI
/
2
*
i
+
2
*
Math
.
PI
*
time
/
period
)));
g
.
setTransform
(
originalTransform
);
}
/**
* Changes the size of the canvas effectively changing the size of the window.
*
* @param width width of the canvas
* @param height height of the canvas
*/
public
static
void
setCanvasSize
(
int
width
,
int
height
)
{
Turtle
.
width
=
width
;
Turtle
.
height
=
height
;
Turtle
.
setupBuffering
();
window
.
pack
();
updateAll
();
}
/**
* Saves the visible canvas to an image.
*
* @param filename image filename
*/
public
static
void
save
(
String
filename
)
{
save
(
new
File
(
filename
));
}
private
static
void
save
(
File
file
)
{
WritableRaster
raster
=
onscreenImage
.
getRaster
();
WritableRaster
newRaster
;
newRaster
=
raster
.
createWritableChild
(
0
,
0
,
width
,
height
,
0
,
0
,
new
int
[]
{
0
,
1
,
2
});
DirectColorModel
cm
=
(
DirectColorModel
)
onscreenImage
.
getColorModel
();
DirectColorModel
newCM
=
new
DirectColorModel
(
cm
.
getPixelSize
(),
cm
.
getRedMask
(),
cm
.
getGreenMask
(),
cm
.
getBlueMask
());
BufferedImage
rgbBuffer
=
new
BufferedImage
(
newCM
,
newRaster
,
false
,
null
);
try
{
String
suffix
=
file
.
getName
().
substring
(
file
.
getName
().
lastIndexOf
(
'.'
)
+
1
);
if
(!
ImageIO
.
write
(
rgbBuffer
,
suffix
,
file
))
throw
new
Exception
(
"Didn't save file."
);
}
catch
(
Exception
e
)
{
file
.
delete
();
JOptionPane
.
showMessageDialog
(
window
,
"Sorry! We can not process your request at this time."
,
"Image Save Failed"
,
JOptionPane
.
ERROR_MESSAGE
);
}
}
/**
* Demo program
*
* @param a commandline args
*/
public
static
void
main
(
String
[]
a
)
{
//Turtle bob = new Turtle();
/*for(int i=0;i<360;i++)
{
bob.forward(i*1.25);
bob.left(90.25);
}
*/
/*If you don't know what a for loop is yet this is equivalent to repeating the middle 4 lines 5 times in a row.*/
Turtle
bob
=
new
Turtle
();
bgcolor
(
"lightblue"
);
bob
.
penColor
(
"red"
);
bob
.
width
(
10
);
for
(
int
i
=
0
;
i
<
200
;
i
++)
{
bob
.
forward
(
i
/
10
.);
bob
.
left
(
5
);
if
(
i
%
10
==
0
)
bob
.
dot
(
"orange"
);
//Draws dots when i is a multiple of 10.
}
bob
.
saveGCODE
(
"test.gcode"
);
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
actionPerformed
(
ActionEvent
e
)
{
if
(((
JMenuItem
)
e
.
getSource
()).
getText
().
equals
(
"Save..."
))
{
JFileChooser
chooser
=
new
JFileChooser
(
System
.
getProperty
(
"user.dir"
));
chooser
.
setFileFilter
(
new
FileNameExtensionFilter
(
"Image (*.jpg, *.jpeg, *.gif, *.bmp, *.png)"
,
"jpg"
,
"png"
,
"jpeg"
,
"bmp"
,
"gif"
));
int
option
=
chooser
.
showSaveDialog
(
window
);
if
(
option
==
JFileChooser
.
APPROVE_OPTION
)
{
if
(
chooser
.
getSelectedFile
()!=
null
)
{
File
file
=
chooser
.
getSelectedFile
();
save
(
file
);
}
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseClicked
(
MouseEvent
e
)
{
if
(
e
.
getModifiers
()==
8
&&
e
.
getClickCount
()==
2
)
{
centerX
=
0
;
centerY
=
0
;
scale
=
1
;
updateAll
();
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseEntered
(
MouseEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseExited
(
MouseEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mousePressed
(
MouseEvent
e
)
{
dragx
=
e
.
getX
();
dragy
=
e
.
getY
();
modifiers
+=
e
.
getModifiers
();
synchronized
(
turtleLock
)
{
for
(
Turtle
t:
turtles
)
{
if
(
t
.
contains
(
dragx
,
dragy
))
t
.
select
();
else
t
.
unselect
();
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseReleased
(
MouseEvent
e
)
{
modifiers
-=
e
.
getModifiers
();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseDragged
(
MouseEvent
e
)
{
modifiers
=
e
.
getModifiers
();
int
dx
,
dy
;
if
(
e
.
getModifiers
()==
8
)
{
x
=
e
.
getX
();
dx
=
x
-
dragx
;
y
=
e
.
getY
();
dy
=
y
-
dragy
;
dragx
=
x
;
dragy
=
y
;
synchronized
(
turtleLock
)
{
centerX
-=
dx
*
1.0
/
scale
;
centerY
+=
dy
*
1.0
/
scale
;
}
updateAll
();
}
this
.
x
=
e
.
getX
();
this
.
y
=
e
.
getY
();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseMoved
(
MouseEvent
e
)
{
modifiers
=
e
.
getModifiers
();
x
=
e
.
getX
();
y
=
e
.
getY
();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
keyTyped
(
KeyEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
keyPressed
(
KeyEvent
e
)
{
String
keyText
=
KeyEvent
.
getKeyText
(
e
.
getKeyCode
()).
toLowerCase
();
synchronized
(
keyLock
)
{
keysDown
.
add
(
keyText
);
if
(
keyBindings
.
containsKey
(
keyText
))
{
unprocessedKeys
.
add
(
keyText
);
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
keyReleased
(
KeyEvent
e
)
{
String
keyText
=
KeyEvent
.
getKeyText
(
e
.
getKeyCode
()).
toLowerCase
();
synchronized
(
keyLock
)
{
keysDown
.
remove
(
keyText
);
processedKeys
.
remove
(
keyText
);}
}
private
void
processKeys
()
{
//System.out.println(keysDown);
TreeSet
<
String
>
keysDownCopy
=
new
TreeSet
<
String
>();
synchronized
(
keyLock
)
{
keysDownCopy
=(
TreeSet
<
String
>)
keysDown
.
clone
();}
keysDownCopy
.
addAll
(
unprocessedKeys
);
for
(
String
keyText:
keysDownCopy
)
{
if
(
keyBindings
.
containsKey
(
keyText
))
{
for
(
ArrayList
binding:
keyBindings
.
get
(
keyText
))
{
Turtle
t
=(
Turtle
)
binding
.
get
(
0
);
String
className
=(
String
)
binding
.
get
(
1
);
String
methodName
=(
String
)
binding
.
get
(
2
);
Boolean
repeat
=(
Boolean
)
binding
.
get
(
3
);
if
(!
repeat
&&
processedKeys
.
contains
(
keyText
))
break
;
unprocessedKeys
.
remove
(
keyText
);
processedKeys
.
add
(
keyText
);
try
{
Class
cls
=
Class
.
forName
(
className
);
Object
clsInstance
=
(
Object
)
cls
.
newInstance
();
Method
m
=
clsInstance
.
getClass
().
getMethod
(
methodName
,
t
.
getClass
());
m
.
invoke
(
clsInstance
,
t
);
}
catch
(
Exception
e1
)
{
try
{
Class
cls
=
Class
.
forName
(
className
);
Object
clsInstance
=
(
Object
)
cls
.
newInstance
();
Method
m
=
clsInstance
.
getClass
().
getMethod
(
methodName
,
t
.
getClass
(),
keyText
.
getClass
());
m
.
invoke
(
clsInstance
,
t
,
keyText
);
}
catch
(
Exception
e2
)
{
try
{
Class
cls
=
Class
.
forName
(
className
);
Object
clsInstance
=
(
Object
)
cls
.
newInstance
();
Method
m
=
clsInstance
.
getClass
().
getMethod
(
methodName
);
m
.
invoke
(
clsInstance
);
}
catch
(
Exception
e3
)
{
System
.
out
.
println
(
"KeyBinding for "
+
keyText
+
" has failed."
);
e1
.
printStackTrace
();
e2
.
printStackTrace
();
e3
.
printStackTrace
();
}
}
}
}
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
componentHidden
(
ComponentEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
componentMoved
(
ComponentEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
componentResized
(
ComponentEvent
e
)
{
width
=(
int
)
draw
.
getBounds
().
getWidth
();
height
=(
int
)
draw
.
getBounds
().
getHeight
();
setupBuffering
();
updateAll
();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
componentShown
(
ComponentEvent
e
)
{}
/**
* Internal mehod for handling events.
* @param e event
*/
public
void
mouseWheelMoved
(
MouseWheelEvent
e
)
{
int
notches
=
e
.
getWheelRotation
();
double
ds
=
Math
.
pow
(
1.1
,
notches
);
x
=
e
.
getX
();
y
=
e
.
getY
();
double
dx
=
width
/
2
-
x
;
double
dy
=
height
/
2
-
y
;
synchronized
(
turtleLock
)
{
centerX
-=(
dx
*
ds
-
dx
)/
scale
/
ds
;
centerY
+=(
dy
*
ds
-
dy
)/
scale
/
ds
;
scale
*=
ds
;
}
updateAll
();
}
/**
* Get the pressed keys.
*
* @return a list of pressed keys
*/
public
static
String
[]
keysDown
()
{
return
keysDown
.
toArray
(
new
String
[]{});
}
/**
* Test if a key is pressed or not.
*
* @param key key you are testing
* @return true if the key is pressed
*/
public
static
boolean
isKeyDown
(
String
key
)
{
return
keysDown
.
contains
(
key
);
}
/**
* Get the mouse x coordinate using the screens coordinate system.
*
* @return x coordinate
*/
public
static
int
mouseX
()
{
return
turtle
.
x
;
}
/**
* Get the mouse y coordinate using the screens coordinate system.
*
* @return y coordinate
*/
public
static
int
mouseY
()
{
return
turtle
.
y
;
}
/**
* Check to see if a mouse button is down.
*
* @return true if a button is down
*/
public
static
boolean
mouseButton
()
{
return
mouseButton1
()
||
mouseButton2
()
||
mouseButton3
();
}
/**
* Check to see if the first mouse button is down.
*
* @return true if button 1 is down
*/
public
static
boolean
mouseButton1
()
{
return
(
turtle
.
modifiers
&
16
)==
16
;
}
/**
* Check to see if the second mouse button is down.
*
* @return true if button 2 is down
*/
public
static
boolean
mouseButton2
()
{
return
(
turtle
.
modifiers
&
8
)==
8
;
}
/**
* Check to see if the third mouse button is down.
*
* @return true if button 3 is down
*/
public
static
boolean
mouseButton3
()
{
return
(
turtle
.
modifiers
&
4
)==
4
;
}
/**
* Converts screen coordinates to canvas coordinates.
*
* @param screenX screen x coordinate
* @return canvas x coordinate
*/
public
static
double
canvasX
(
double
screenX
)
{
return
(
screenX
-
width
/
2.0
)/
scale
+
centerX
;
}
/**
* Converts screen coordinates to canvas coordinates.
*
* @param screenY screen y coordinate
* @return canvas y coordinate
*/
public
static
double
canvasY
(
double
screenY
)
{
return
(-
screenY
+
height
/
2.0
)/
scale
+
centerY
;
}
public
static
double
screenX
(
double
canvasX
)
{
return
(
canvasX
-
centerX
)*
scale
+
width
/
2.0
;
}
public
static
double
screenY
(
double
canvasY
)
{
return
(
canvasY
-
centerY
)*
scale
+
height
/
2.0
;
}
private
static
void
saveGCODE
(
String
filename
)
{
PrintWriter
out
=
new
PrintWriter
(
System
.
out
);
try
{
out
=
new
PrintWriter
(
filename
);
}
catch
(
Exception
e
)
{
}
out
.
println
(
"M104 S200"
);
out
.
println
(
"M109 S200"
);
out
.
println
(
"G21"
);
out
.
println
(
"G90"
);
out
.
println
(
"M82"
);
out
.
println
(
"M106"
);
out
.
println
(
"G28 X0 Y0"
);
out
.
println
(
"G28 Z0"
);
out
.
println
(
"G29"
);
out
.
println
(
"G1 Z15.0 F9000"
);
out
.
println
(
"G92 E0"
);
out
.
println
(
"G1 F200 E5"
);
out
.
println
(
"G92 E0"
);
out
.
println
(
"G1 X50 Y50 F1800"
);
double
e
=
0
;
synchronized
(
turtleLock
)
{
int
i
=
0
;
for
(
Map
.
Entry
<
Long
,
ArrayList
>
entry
:
turtleStates
.
entrySet
())
{
retrieveState
(
entry
.
getKey
());
Turtle
t
=
getStateTurtle
(
entry
.
getValue
());
i
++;
if
(
i
==
1
)
continue
;
if
(
t
.
__location
!=
null
&&
!
t
.
__location
.
equals
(
t
.
_location
))
{
double
x1
=
t
.
_location
.
x
,
y1
=
t
.
_location
.
y
,
x2
=
t
.
__location
.
x
,
y2
=
t
.
__location
.
y
;
double
d
=
Math
.
hypot
(
x1
-
x2
,
y1
-
y2
);
e
+=
d
*
0.05
;
//System.out.printf("%f %f %f %f",x1,y1,x2,y2);
if
(
t
.
_isPenDown
)
{
out
.
printf
(
"G1 X%.4f Y%.4f E%.4f\n"
,
screenX
(
x1
)*
1.0
/
width
*
100
,
screenY
(
y1
)*
1.0
/
height
*
100
,
e
);
}
else
{
}
}
}
out
.
println
(
"G1 Z15"
);
out
.
println
(
"M104 S0"
);
out
.
println
(
"M140 S0"
);
out
.
close
();
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment