import java.util.Iterator; import java.util.Vector; public class ScalarFieldUtils { public static class ScalarFieldProduct implements IScalarField { Vector m_vecFields; public ScalarFieldProduct() {} public ScalarFieldProduct(IScalarField src) { m_vecFields = new Vector(5); m_vecFields.add(src.makeCopy()); } public ScalarFieldProduct(IScalarField src1,IScalarField src2) { m_vecFields = new Vector(5); m_vecFields.add(src1.makeCopy()); m_vecFields.add(src2.makeCopy()); } public ScalarFieldProduct(ScalarFieldProduct src) { m_vecFields = new Vector(src.m_vecFields.size()); Iterator iter = src.m_vecFields.iterator(); while(iter.hasNext()) { m_vecFields.add(iter.next().makeCopy()); } } public void addField(IScalarField src) { m_vecFields.add(src.makeCopy()); } public double getVal(double [] arrLfLoc) { double lfProduct = 1.0; Iterator iter = m_vecFields.iterator(); while(iter.hasNext()) { lfProduct *= iter.next().getVal(arrLfLoc); } return lfProduct; } /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @return gradient (of proper dimensionality) as a double [] */ public double [] getGradient(double arrLoc[]) { double arrLfAccum[] = new double[arrLoc.length]; double arrLfTmp[] = new double[arrLoc.length]; Iterator iter = m_vecFields.iterator(); double lfCurrVal = 1.0; while(iter.hasNext()) { IScalarField currField = iter.next(); double lfVal = currField.getVal(arrLoc); double [] arrLfNextGrad = currField.getGradient(arrLoc); for(int i = 0; i < arrLfAccum.length; ++i) { arrLfTmp[i] = arrLfAccum[i]; } for(int i = 0; i < arrLfAccum.length; ++i) { arrLfAccum[i] = lfCurrVal*arrLfNextGrad[i] + lfVal*arrLfTmp[i]; } lfCurrVal *= lfVal; } return arrLfAccum; } double [] m_arrLfTmp; /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @param arrRslt gradient (of proper dimensionality) as a double [] */ public void getGradient(double arrLoc[], double arrRslt[]) { double arrLfAccum[] = arrRslt; if(m_arrLfTmp == null || m_arrLfTmp.length < arrLoc.length) { m_arrLfTmp = new double[arrLoc.length]; } Iterator iter = m_vecFields.iterator(); double lfCurrVal = 1.0; while(iter.hasNext()) { IScalarField currField = iter.next(); double lfVal = currField.getVal(arrLoc); double [] arrLfNextGrad = currField.getGradient(arrLoc); for(int i = 0; i < arrLfAccum.length; ++i) { m_arrLfTmp[i] = arrLfAccum[i]; } for(int i = 0; i < arrLfAccum.length; ++i) { arrLfAccum[i] = lfCurrVal*arrLfNextGrad[i] + lfVal*m_arrLfTmp[i]; } lfCurrVal *= lfVal; } } public IScalarField makeCopy() { return new ScalarFieldProduct(this); } } public static class ScalarFieldFromEnv implements IScalarField { IEnvironment m_env; int m_nFieldIdx; public ScalarFieldFromEnv() { m_env = new TrivialEnvironment(); } public ScalarFieldFromEnv(IEnvironment envToWrap, int nIdxField) { m_nFieldIdx = nIdxField; m_env = envToWrap.makeCopy(); } public ScalarFieldFromEnv(ScalarFieldFromEnv src) { m_nFieldIdx = src.m_nFieldIdx; m_env = src.m_env.makeCopy(); } /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @return gradient (of proper dimensionality) as a double [] */ public double [] getGradient(double arrLoc[]) { return m_env.getGradient(m_nFieldIdx, arrLoc); } /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @param arrRslt gradient (of proper dimensionality) as a double [] */ public void getGradient(double arrLoc[], double arrRslt []) { m_env.getGradient(m_nFieldIdx, arrLoc, arrRslt); } public double getVal(double [] arrLfLoc) { return m_env.getFieldVal(m_nFieldIdx, arrLfLoc); } public IScalarField makeCopy() { return new ScalarFieldFromEnv(this); } } public static class LinearScalarField implements IScalarField { double m_lfOffset; double [] m_arrLfDirVec; double [] m_arrLfCenter; public LinearScalarField() { m_arrLfDirVec = new double[2]; // default dimensionality is 2 m_arrLfCenter = new double[2]; } public LinearScalarField(double lfOffset) { m_arrLfDirVec = new double[2]; // default dimensionality is 2 m_arrLfCenter = new double[2]; m_lfOffset = lfOffset; } public LinearScalarField(double lfCX, double lfCY, int nAxis, double lfOffset) { m_arrLfDirVec = new double[2]; // default dimensionality is 2 m_arrLfCenter = new double[2]; m_arrLfCenter[0] = lfCX; m_arrLfCenter[1] = lfCY; m_arrLfDirVec[nAxis] = 1.0; m_lfOffset = lfOffset; } public double [] accessCtrVec() { return m_arrLfCenter; } public double [] accessDirVec() { return m_arrLfDirVec; } public void setCtrVec(double [] ctrVec) { m_arrLfCenter = MathUtils.arrDblCpy(ctrVec, ctrVec.length); } public void setDirVec(double [] dirVec) { m_arrLfDirVec = MathUtils.arrDblCpy(dirVec, dirVec.length); } public void setOffset(double lfOff) { m_lfOffset = lfOff; } public LinearScalarField(LinearScalarField src) { m_arrLfDirVec = MathUtils.arrDblCpy(src.m_arrLfDirVec, src.m_arrLfDirVec.length); m_arrLfCenter = MathUtils.arrDblCpy(src.m_arrLfCenter, src.m_arrLfCenter.length); m_lfOffset = src.m_lfOffset; } public double getVal(double [] arrLfLoc) { double lfResult = m_lfOffset; for(int i = 0; i < m_arrLfDirVec.length; ++i) { lfResult = lfResult + (arrLfLoc[i]-m_arrLfCenter[i])*m_arrLfDirVec[i]; } return lfResult; } /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @return gradient (of proper dimensionality) as a double [] */ public double [] getGradient(double arrLoc[]) { return MathUtils.arrDblCpy(m_arrLfDirVec, m_arrLfDirVec.length); } /** * Gradient at a particular location * @param arrLoc place at which to take gradient * @param arrRslt gradient (of proper dimensionality) as a double [] */ public void getGradient(double arrLoc[], double arrRslt[]) { for(int i = 0; i < m_arrLfDirVec.length; ++i) { arrRslt[i] = m_arrLfDirVec[i]; } } public IScalarField makeCopy() { return new LinearScalarField(this); } } }