package edu.stanford.rsl.conrad.phantom.forbild.shapes; import java.util.ArrayList; import java.util.Iterator; import java.util.Scanner; import edu.stanford.rsl.conrad.geometry.AbstractShape; import edu.stanford.rsl.conrad.geometry.bounds.HalfSpaceBoundingCondition; import edu.stanford.rsl.conrad.geometry.shapes.simple.Box; import edu.stanford.rsl.conrad.geometry.shapes.simple.Plane3D; import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND; import edu.stanford.rsl.conrad.geometry.transforms.AffineTransform; import edu.stanford.rsl.conrad.numerics.SimpleMatrix; import edu.stanford.rsl.conrad.numerics.SimpleVector; import edu.stanford.rsl.conrad.numerics.mathexpressions.Evaluator; /** * <p>This class creates a surface from a <a href = "http://www.imp.uni-erlangen.de/forbild/english/forbild/index.htm">forbild</a>definition.</p> * <p>The expression [Box: x=originX; y=originY; z=originZ; dx=length; dy=width; dz= height] defines a box located at (originX,originY,originZ).</p> * * @author Rotimi .X. Ojo */ public class ForbildBox extends Box { private static final long serialVersionUID = 4063615482635066034L; private PointND surfaceOrigin = new PointND(0,0,0); private ArrayList<Plane3D> boundingPlanes = new ArrayList<Plane3D>(); private double dx; private double dy; private double dz; public ForbildBox(String expression){ parseExpression(expression); SimpleMatrix rot = new SimpleMatrix(3,3); rot.identity(); transform = new AffineTransform(rot, new SimpleVector(3)); correctAndAddBoundingConditions(); surfaceOrigin.set(0, surfaceOrigin.get(0)-dx/2); surfaceOrigin.set(1, surfaceOrigin.get(1)-dy/2); surfaceOrigin.set(2, surfaceOrigin.get(2)-dz/2); super.init(surfaceOrigin, dx, dy , dz); } public ForbildBox(ForbildBox fb){ super(fb); dx = fb.dx; dy = fb.dy; dz = fb.dz; surfaceOrigin = (fb.surfaceOrigin != null) ? fb.surfaceOrigin.clone() : null; if (fb.boundingPlanes != null){ boundingPlanes = new ArrayList<Plane3D>(); Iterator<Plane3D> it = fb.boundingPlanes.iterator(); while (it.hasNext()) { Plane3D pl = it.next(); boundingPlanes.add((pl!=null) ? new Plane3D(pl) : null); } } else{ boundingPlanes = null; } } private void parseExpression(String expression) { expression = expression.trim(); if(expression.charAt(0)=='(' && expression.charAt(expression.length()-1)==')'){ expression = expression.substring(1,expression.length()-1); } String props = expression.substring(expression.indexOf(':')+ 1).trim(); Scanner sc = new Scanner(props); sc.useDelimiter(";"); while(sc.hasNext()){ String currProp = sc.next().trim(); if(currProp.charAt(0)== 'x'&& currProp.contains("=")){ surfaceOrigin.set(0,Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1))); }else if(currProp.charAt(0)== 'y'&& currProp.contains("=")){ surfaceOrigin.set(1,Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1))); }else if(currProp.charAt(0)== 'z' && currProp.contains("=")){ surfaceOrigin.set(2,Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1))); }else if(currProp.indexOf("dx")==0){ dx = Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1)); }else if(currProp.indexOf("dy")==0){ dy = Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1)); }else if(currProp.indexOf("dz")==0){ dz = Evaluator.getValue(currProp.substring(currProp.indexOf('=')+1)); }else if(currProp.contains("r") && (currProp.contains(">") || currProp.contains("<"))){ boundingPlanes.add(Evaluator.getPlane(currProp)); } } } /** * Moves bounding planes from world space to the space of the bounded object * Creates a bounding condition using this new plane and updates the superclass */ private void correctAndAddBoundingConditions() { Iterator<Plane3D> it = boundingPlanes.iterator(); while(it.hasNext()){ Plane3D currPlane = it.next(); currPlane.applyTransform(transform.inverse()); addBoundingCondition(new HalfSpaceBoundingCondition(currPlane)); } } @Override public AbstractShape clone() { return new ForbildBox(this); } } /* * Copyright (C) 2010-2014 Rotimi X Ojo * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */