import java.awt.Graphics; import java.awt.RenderingHints; public class EnvDrawContour implements IEnvDraw { int m_nNumSteps; int m_nNumTraces; double m_lfStepScale; static int m_nNewtonIter = 3; double m_arrLfTracePts[]; java.awt.image.BufferedImage m_imageBuf=null; public EnvDrawContour() {m_nNumSteps = 25; m_lfStepScale = 0.0025; m_nNumTraces = 500;} /** * * @param nNumSteps number of numerical steps each contour line takes * @param nNumTraces number of countour lines * @param lfStepScale I forget what this does */ public EnvDrawContour(int nNumSteps, int nNumTraces, double lfStepScale) { m_nNumSteps = nNumSteps; m_nNumTraces = nNumTraces; m_lfStepScale = lfStepScale; } static void stepSideways(double [] arrLfLoc, IEnvironment env, double lfStepScale, boolean bLeftRight, double [] arrLfTmp) { env.getGradient(0, arrLfLoc, arrLfTmp); double lfTmpSqrd = arrLfTmp[0]*arrLfTmp[0] + arrLfTmp[1]*arrLfTmp[1]; double lfScale = Math.sqrt(lfTmpSqrd); if(lfScale > MathUtils.lfEps) { lfScale = 1.0/lfScale; } if(bLeftRight) { double lfSwp = arrLfTmp[0]; arrLfTmp[0] = -arrLfTmp[1]; arrLfTmp[1] = lfSwp; } else { double lfSwp = arrLfTmp[0]; arrLfTmp[0] = arrLfTmp[1]; arrLfTmp[1] = -lfSwp; } arrLfLoc[0] += lfScale*lfStepScale*arrLfTmp[0]; arrLfLoc[1] += lfScale*lfStepScale*arrLfTmp[1]; } static void stepToLevel(double [] arrLfLoc, IEnvironment env, double lfStepScale, double lfLevel, double [] arrLfTmp) { double lfCurrVal = env.getFieldVal(0, arrLfLoc); int nIter = 0; while(Math.abs(lfLevel-lfCurrVal) > MathUtils.lfEps && nIter < m_nNewtonIter) { env.getGradient(0, arrLfLoc, arrLfTmp); double lfGradSqrd = arrLfTmp[0]*arrLfTmp[0] + arrLfTmp[1]*arrLfTmp[1]; if(Math.abs(lfGradSqrd) > MathUtils.lfEps) { lfGradSqrd = 1.0/lfGradSqrd; } else { lfGradSqrd = 1.0; // 1.0 is almost infinity, right? } double lfErr = lfCurrVal - lfLevel; arrLfLoc[0] -= lfStepScale*lfErr*arrLfTmp[0]*lfGradSqrd; arrLfLoc[1] -= lfStepScale*lfErr*arrLfTmp[1]*lfGradSqrd; ++nIter; lfCurrVal = env.getFieldVal(0, arrLfLoc); } ++nIter; } IColorMap m_currColorMap = null; static void pickRandomStart(double arrLfStart[], double [] arrLfMin, double [] arrLfMax) { for(int i = 0; i < arrLfStart.length; ++i) { arrLfStart[i] = Math.random(); arrLfStart[i] = arrLfStart[i]*(arrLfMax[i]-arrLfMin[i]) + arrLfMin[i]; } } /* * int m_nNumSteps; int m_nNumTraces; double m_lfStepScale; double m_arrLfTracePts[]; */ public void draw(IEnvironment env, IProjection proj, java.awt.Graphics g) { if(m_arrLfTracePts == null) { setTracePts(env); } java.awt.Graphics2D tmpDraw = null; proj.width(); if(m_imageBuf == null || m_imageBuf.getWidth() != proj.width() || m_imageBuf.getHeight() != proj.height() || m_currColorMap != globalsUI.getColorMap()) { m_imageBuf = new java.awt.image.BufferedImage(proj.width(), proj.height(), java.awt.image.BufferedImage.TYPE_INT_ARGB); tmpDraw = m_imageBuf.createGraphics(); tmpDraw.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // Anti-alias! RenderingHints.VALUE_ANTIALIAS_ON); m_currColorMap = globalsUI.getColorMap(); } if(tmpDraw != null) { System.out.println("EnvDrawContour: re-drawing\n"); tmpDraw.setBackground(globalsUI.getColorMap().getColor(0)); int nLineWidth = globalsUI.getInstance().getLineThickness(); nLineWidth = (nLineWidth+1)/2; tmpDraw.setStroke(new java.awt.BasicStroke(nLineWidth)); tmpDraw.setColor(globalsUI.getColorMap().getColor(0)); tmpDraw.clearRect(0, 0, proj.width(), proj.height()); for(int i = 0; i < m_nNumTraces; ++i) { tmpDraw.setColor(globalsUI.getColorMap().getColor(3)); for(int j = 0; j < m_nNumSteps-1; ++j) { // do drawing here int nIdx = 2*(i*m_nNumSteps+j); tmpDraw.drawLine(proj.getScreenComp(0, m_arrLfTracePts, nIdx) - proj.left(), proj.getScreenComp(1, m_arrLfTracePts, nIdx) - proj.top(), proj.getScreenComp(0, m_arrLfTracePts, nIdx+2) - proj.left(), proj.getScreenComp(1, m_arrLfTracePts, nIdx+2) - proj.top()); } } } g.drawImage(m_imageBuf, proj.left(),proj.top(),null); } public void setTracePts(IEnvironment env) { m_arrLfTracePts = new double[m_nNumTraces*m_nNumSteps*2]; int nNumCurves = m_nNumTraces; double [] arrLfLoc = new double[env.getDimensionality()]; double [] arrLfNextLoc = new double[env.getDimensionality()]; double [] arrLfTmp = new double[env.getDimensionality()]; double [] arrLfSwp = null; double [] arrLfMin = env.getBoundary().bboxMinCorner(); double [] arrLfMax = env.getBoundary().bboxMaxCorner(); for(int i = 0; i < nNumCurves; ++i) { pickRandomStart(arrLfLoc, arrLfMin, arrLfMax); double lfLevel = env.getFieldVal(0, arrLfLoc); arrLfNextLoc[0] = arrLfLoc[0]; arrLfNextLoc[1] = arrLfLoc[1]; for(int nStep = 0; nStep < m_nNumSteps; ++nStep) { stepSideways(arrLfNextLoc, env, m_lfStepScale, true, arrLfTmp); stepToLevel(arrLfNextLoc, env, m_lfStepScale, lfLevel, arrLfTmp); int nIdx = 2*(m_nNumSteps*i+nStep); m_arrLfTracePts[nIdx] = arrLfLoc[0]; m_arrLfTracePts[nIdx+1] = arrLfLoc[1]; // add it here arrLfSwp = arrLfNextLoc; arrLfNextLoc = arrLfLoc; arrLfLoc = arrLfSwp; } } } }