one.empty3.growth.LSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of empty3-library-3d Show documentation
Show all versions of empty3-library-3d Show documentation
3D rendering engine. Plus modeling. Expected glsl textures 3d and 2d rendering
/*
* Copyright (c) 2023. Manuel Daniel Dahmen
*
*
* Copyright 2012-2023 Manuel Daniel Dahmen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package one.empty3.growth;
import one.empty3.growth.graphics.Turtle2D;
import java.util.*;
import java.util.function.BiConsumer;
public class LSystem {
private static final int MAX = 100;
private int t = 0;
private HashMap rules = new HashMap<>();
private List symbols = new ArrayList<>();
private HashSet constants = new HashSet<>();
private Parameters parameters;
private Map initialParameters = new HashMap<>();
private boolean init = false;
public LSystem() {
initFirstSymbols();
}
/***
* Call it just after constructor. // TODO Refactor
*/
public void init() {
if (!init)
parameters = new Parameters(this);
init = true;
}
public void addInitialParameter(Symbol symbol, Parameter parameter) {
initialParameters.put(symbol, parameter);
}
public void addRule(SymbolSequence ss, SymbolSequence action) {
rules.put(ss.parts(), action);
}
public void addInitialParam(Symbol symbol, Parameter parameter) throws Exception {
initialParameters.put(symbol, parameter);
}
public Parameter getInitialParam(Symbol key) {
return initialParameters.get(key);
}
public Parameter getParam(int t, String name) {
return parameters.getParameter(t, name);
}
public HashMap getParams(int t) {
return parameters.getParameters(t);
}
public HashMap getRules() {
return rules;
}
private void initFirstSymbols() {
t = 0;
symbols = new ArrayList<>();
}
public SymbolSequence applyRules() throws NotWellFormattedSystem {
/***
* After this method call, the added sequence will
* contains the current symbols of the system
*/
if (getCurrentSymbols() == null) {
throw new NotWellFormattedSystem("no cuurent symobols");
}
SymbolSequence data = getCurrentSymbols().parts();
SymbolSequence rest = new SymbolSequence();
for (int i = 0; i < data.size(); i++) {
int ok = 0;
for (Map.Entry entry : rules.entrySet()) {
SymbolSequence symbols = entry.getKey().parts();
SymbolSequence replacement = entry.getValue().parts();
for (int j = 0; j < symbols.size() &&
i + j < data.size()
; j++) {
if (data.get(i + j).equals(symbols.get(j))) {
ok++;
} else {
ok = 0;
}
if (ok == symbols.size() && ok > 0) {
rest.addAll(replacement);
i = i + j;
ok = 0;
break;
}
}
}
if (ok == 0) {
rest.add(data.get(i));
}
}
t++;
updateParams();
symbols.add(rest);
//Logger.getAnonymousLogger().log(Level.INFO, this);
return rest;
}
public void addRule(String search, String replacement) {
SymbolSequence[] rule = new SymbolSequence[2];
rule[0] = new SymbolSequence();
rule[1] = new SymbolSequence();
byte[] searBytes = search.getBytes();
byte[] replBytes = replacement.getBytes();
for (byte searByte : searBytes) {
rule[0].add(new Symbol((char) searByte));
}
for (byte replByte : replBytes) {
rule[1].add(new Symbol((char) replByte));
}
addRule(rule[0], rule[1]);
}
public void addInitialSymbols(String is) {
SymbolSequence start = new SymbolSequence();
byte[] replBytes = is.getBytes();
for (byte searByte : replBytes) {
start.add(new Symbol((char) searByte));
}
setCurrentSymbols(start);
}
private void updateParams() {
HashMap parameters = this.parameters.getParameters(t - 1);
if (parameters != null)
parameters.forEach(new BiConsumer() {
@Override
public void accept(String s, Parameter parameter) {
if (parameter != null) {
FunctionalParameter f;
f = new FunctionalParameter(
parameter.getName(),
parameter.eval(getT(), 0),
parameter.getFormula());
LSystem.this.parameters.addParameter(t, f);
}
}
});
}
public void sequenceGraphics(Turtle2D turtle2D) {
}
// TODO Vérifier cette méthode.
public SymbolSequence getCurrentSymbols() {
if (symbols.size() == 0) {
SymbolSequence ss;
symbols.add(ss = new SymbolSequence());
initialParameters.forEach((symbol, parameter) -> ss.add(symbol));
return symbols.get(0);
}
if (symbols.size() < t)
return symbols.get(symbols.size() - 1);
return symbols.get(t);
}
public void setCurrentSymbols(SymbolSequence ss) {
symbols.add(ss);
}
public String toString() {
final String[] s = {"LSystem(t==" + t + "\n"};
for (int i = 0; i < symbols.size(); i++) {
s[0] += "\nData\nSTEP" + i + "\n----\n";
s[0] += symbols.get(i).parts().toString();
}
s[0] += "\nParameters values: \n";
s[0] += parameters.toString();
s[0] += "\nInitial parameters: \n";
initialParameters.forEach(new BiConsumer() {
@Override
public void accept(Symbol symbol, Parameter parameter) {
s[0] += "Symbol : " + symbol.getValue() + " Parameter : " + parameter.toString() + "\n";
}
});
s[0] += "\nRules:\n";
rules.forEach(new BiConsumer() {
@Override
public void accept(SymbolSequence symbolSequence, SymbolSequence action) {
s[0] += "RULE\n" + symbolSequence.toString() + "\t==>>> " + action.toString() + "\n";
}
});
return s[0];
}
public Map getInitialParameters() {
HashMap params = new HashMap();
initialParameters.forEach(new BiConsumer() {
@Override
public void accept(Symbol symbol, Parameter parameter) {
params.put(symbol.getValue().toString(), parameter.getValue());
}
});
return initialParameters;
}
int i = 0;
public int getT() {
return t;
}
public void addParameter(int t, Parameter functionalParameter) {
functionalParameter.lSystem = this;
if (t == 0) {
addInitialParam(functionalParameter);
}
parameters.addParameter(t, functionalParameter);
}
public void addInitialParam(Parameter f) {
f.lSystem = this;
parameters.addParameter(0, f);
}
public void setCurrentSymbols(String a) {
SymbolSequence start = new SymbolSequence();
byte[] replBytes = a.getBytes();
for (byte searByte : replBytes) {
start.add(new Symbol((char) searByte));
}
setCurrentSymbols(start);
}
}