package de.gaalop.visualizer.zerofinding; import de.gaalop.dfg.MultivectorComponent; import de.gaalop.visualizer.Point3d; import java.util.HashMap; import java.util.LinkedList; /** * Implements a zero finder method thread, which samples a cube and searches at * every sample point in a neighborhood along the gradient a zero point * @author christian */ public class GradientMethodThread extends Thread { private float fromOX_Incl; private float toOX_Excl; private float a ; private float dist; private HashMap<MultivectorComponent, Double> globalValues; private CodePiece codePiece; public LinkedList<Point3d> points = new LinkedList<Point3d>(); private int max_n; private double epsilon; private boolean renderIn2d; public GradientMethodThread(float fromOX_Incl, float toOX_Excl, float a, float dist, HashMap<MultivectorComponent, Double> globalValues, CodePiece codePiece, double epsilon, int max_n, boolean renderIn2d) { this.fromOX_Incl = fromOX_Incl; this.toOX_Excl = toOX_Excl; this.a = a; this.dist = dist; this.globalValues = globalValues; this.codePiece = codePiece; this.epsilon = epsilon; this.max_n = max_n; this.renderIn2d = renderIn2d; } @Override public void run() { if (renderIn2d) run2d(); else run3d(); } private void run2d() { for (float ox = fromOX_Incl; ox <= toOX_Excl; ox += dist) for (float oy = -a; oy <= a; oy += dist) { float[] resultSearch = searchInNeighborhood(ox,oy,0); if (resultSearch != null) points.add(new Point3d(resultSearch[0],resultSearch[1],resultSearch[2])); } } private void run3d() { for (float ox = fromOX_Incl; ox <= toOX_Excl; ox += dist) for (float oy = -a; oy <= a; oy += dist) for (float oz = -a; oz <= a; oz += dist) { float[] resultSearch = searchInNeighborhood(ox,oy,oz); if (resultSearch != null) points.add(new Point3d(resultSearch[0],resultSearch[1],resultSearch[2])); } } /** * Searches zero points in the neighborhood of a certain point ox,oy,oz along the gradient * @param ox The x-coordinate of the point * @param oy The y-coordinate of the point * @param oz The z-coordinate of the point * @return null, if no zero point was found, other an array with the three coordinates of the zero point */ private float[] searchInNeighborhood(float ox, float oy, float oz) { double distDir = 1; EvaluationResult eval; eval = evaluate(ox, oy, oz); int n = 1; double glastx=eval.gradient.x; double glasty=eval.gradient.y; double glastz=eval.gradient.z; while (Math.abs(eval.f)>epsilon && n<=max_n) { //Gradient: [eval.dx,eval.dy,eval.dz] eval.gradient.normalize(); if (glastx*eval.gradient.x+glasty*eval.gradient.y+glastz*eval.gradient.z<0) { distDir/=2; } //Go into direction of negative gradient ox -= eval.gradient.x*distDir; oy -= eval.gradient.y*distDir; oz -= eval.gradient.z*distDir; glastx=eval.gradient.x; glasty=eval.gradient.y; glastz=eval.gradient.z; eval = evaluate(ox, oy, oz); n++; } if (Math.abs(eval.f)<=epsilon) return new float[] {ox,oy,oz}; else return null; } /** * Evaluates the code piece on a special point ox,oy,oz and returns the result * @param ox The x-coordinate of the point * @param oy The y-coordinate of the point * @param oz The z-coordinate of the point * @return The evaluation result */ private EvaluationResult evaluate(float ox, float oy, float oz) { final String productName = codePiece.nameOfMultivector; HashMap<MultivectorComponent, Double> valuesIn = new HashMap<MultivectorComponent, Double>(globalValues); valuesIn.put(new MultivectorComponent("_V_ox", 0), (double) ox); valuesIn.put(new MultivectorComponent("_V_oy", 0), (double) oy); valuesIn.put(new MultivectorComponent("_V_oz", 0), (double) oz); Evaluater evaluater = new Evaluater(valuesIn); evaluater.evaluate(codePiece); HashMap<MultivectorComponent, Double> valuesOut = evaluater.getValues(); EvaluationResult result = new EvaluationResult(); result.f = valuesOut.get(new MultivectorComponent(productName,0)); result.gradient = new VecN3( valuesOut.get(new MultivectorComponent(productName+"Dx",0)), valuesOut.get(new MultivectorComponent(productName+"Dy",0)), valuesOut.get(new MultivectorComponent(productName+"Dz",0)) ); return result; } }