/
FLTThermal.java
165 lines (143 loc) · 5.04 KB
/
FLTThermal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import Interfaces.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Slide-Erode filter
* Filter class, inverts the current heightmap
*
* @author James Robinson
* @version 1.0
*/
public class FLTThermal implements IFilter, ActionListener, ChangeListener
{
private ICanvasAlg parent;
private JPanel panel;
private JButton btnApply;
private JSlider sldIterations;
private JTextField txtIterations;
private boolean preview = true;
/**
* Sets the parent of this class to the specified instance of
* ICanvasAlg
*
* @param parent The new parent to be set
*/
public void setParent(ICanvasAlg parent)
{
this.parent = parent;
}
public void setPreview(boolean preview)
{
this.preview = preview;
}
/**
* Sets the panel in which the GUI should be implemented
* Any standard swing components can be used
*
* @param panel The GUI panel
*/
public void setPanel(JPanel panel)
{
this.panel = panel;
panel.setLayout(new BorderLayout());
JLabel label = new JLabel("Produces an effect similar to thermal erosion", (int) JLabel.CENTER_ALIGNMENT);
panel.add(label, BorderLayout.PAGE_START);
JPanel iterations = new JPanel();
iterations.setLayout(new FlowLayout());
label = new JLabel("Iterations ");
iterations.add(label);
sldIterations = new JSlider(1, 100, 1);
sldIterations.addChangeListener(this);
iterations.add(sldIterations);
txtIterations = new JTextField(Integer.toString((int)sldIterations.getValue()));
txtIterations.setEditable(false);
txtIterations.setPreferredSize(new Dimension(35, 25));
iterations.add(txtIterations);
panel.add(iterations, BorderLayout.CENTER);
btnApply = new JButton("Apply Thermal Erosion");
btnApply.addActionListener(this);
panel.add(btnApply, BorderLayout.PAGE_END);
if(preview)
parent.refreshMiniView(apply(preview));
}
/*
* Returns a two dimensional integer array representing the heightmap
* with the filter applied
*
* @return int[][] The filter-applied heightmap
*/
private int[][] applyThermal(int[][] heightmap)
{
for(int i = 0; i < heightmap.length; i++) {
for(int j = 0; j < heightmap[i].length; j++) {
for(int i2 = -1; i2 < 2; i2+=2) {
for(int j2 = -1; j2 < 2; j2+=2) {
if((i + i2 > 0) && (i + i2 < heightmap.length) && (j+j2 > 0) && (j + j2 < heightmap[i].length) && heightmap[i+i2][j+j2] > 0) {
int count = 0;
while(((double) (heightmap[i][j] - heightmap[i+i2][j+j2])) > 2 && heightmap[i+i2][j+j2] > 0) {
heightmap[i][j]--;
heightmap[i+i2][j+j2]++;
}
}
}
}
}
}
return heightmap;
}
/**
* Returns a string representing this class, this is displayed in
* the filters combo box
*
* @return String The string representing this class
*/
public String toString()
{
return "Thermal Erosion";
}
private int[][] apply(boolean preview)
{
int[][] heightmap = new int[128][128];
int step = 1;
if(!preview) {
parent.setProgressBar(sldIterations.getValue());
heightmap = parent.cloneArray(parent.getHeightMap());
}
else {
heightmap = parent.getPreviewMap();
step = (int) Math.ceil((double)parent.getHeightMap().length / (double)parent.getPreviewMap().length);
}
for(int i = 0; i < sldIterations.getValue() / step; i++) {
heightmap = applyThermal(heightmap);
if(!preview)
parent.increaseProgressBar();
}
if(!preview)
parent.resetProgressBar();
return heightmap;
}
/**
* Called when an action event occurs, in this case the 'Invert Terrain' button
* is the only component which generates an action event
*
* @param e The action event generated
*/
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(btnApply)) {
parent.amendLog("Applying filter: " + toString());
parent.setHeightMap(apply(false));
}
}
public void stateChanged(ChangeEvent e) {
if (e.getSource().equals(sldIterations)) {
txtIterations.setText(Integer.toString((int)sldIterations.getValue()));
if(preview) {
parent.setPreviewMap(parent.getHeightMap(), 128);
parent.refreshMiniView(apply(preview));
}
}
}
}