/** * Draws this without refreshing steps. * * @param panel the drawing panel requesting the drawing * @param _g the graphics context on which to draw */ public void drawMe(DrawingPanel panel, Graphics _g) { // position and show inspector if requested during loading if (inspectorX != Integer.MIN_VALUE && trackerPanel != null && trackerPanel.getTFrame() != null) { positionInspector(); Runnable runner = new Runnable() { public void run() { showInspector = false; inspector.setVisible(true); } }; if (showInspector) SwingUtilities.invokeLater(runner); } if (isVisible() && isTraceVisible()) { // draw trace only if fixed coords & (non-worldview or no ref frame) TrackerPanel tPanel = (TrackerPanel) panel; ImageCoordSystem coords = tPanel.getCoords(); // get active coords boolean isRefFrame = coords instanceof ReferenceFrame; if (isRefFrame) { coords = ((ReferenceFrame) coords).getCoords(); } boolean fixed = coords.isFixedAngle() && coords.isFixedOrigin() && coords.isFixedScale(); if (fixed && (!(tPanel instanceof WorldTView) || !isRefFrame)) { trace.reset(); for (int i = 0; i < traceX.length; i++) { if (Double.isNaN(traceX[i])) continue; tracePt.setLocation(traceX[i], traceY[i]); java.awt.Point p = tracePt.getScreenPosition(tPanel); if (trace.getCurrentPoint() == null) trace.moveTo((float) p.getX(), (float) p.getY()); else trace.lineTo((float) p.getX(), (float) p.getY()); } Graphics2D g2 = (Graphics2D) _g; Color color = g2.getColor(); Stroke stroke = g2.getStroke(); g2.setColor(getFootprint().getColor()); g2.setStroke(traceStroke); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2.draw(trace); // restore original color and stroke g2.setColor(color); g2.setStroke(stroke); } } super.draw(panel, _g); }
/** Refreshes step positions. */ protected void refreshSteps() { locked = true; if (refreshStepsLater) return; // return if this is an empty dynamic system if (this instanceof DynamicSystem) { DynamicSystem system = (DynamicSystem) this; if (system.particles.length == 0) return; } if (trackerPanel != null) { refreshDerivsLater = trackerPanel.getPlayer().getClipControl().isPlaying(); int n = trackerPanel.getFrameNumber(); VideoClip clip = trackerPanel.getPlayer().getVideoClip(); // determine last frame to be marked (must satisfy both model and clip) int end = Math.min(getEndFrame(), n); while (end > getStartFrame() && !clip.includesFrame(end)) { end--; } if (end <= lastValidFrame) return; if (lastValidFrame == -1) { reset(); // initializes model, sets lastValidFrame to marked frame, if any if (lastValidFrame == -1 || end <= lastValidFrame) return; } int start = lastValidFrame; Tracker.logTime( this.getClass().getSimpleName() + this.hashCode() + " refreshing steps " + start + " to " + end); //$NON-NLS-1$ //$NON-NLS-2$ boolean singleStep = (end - start == 1); // step forward to end ImageCoordSystem coords = trackerPanel.getCoords(); // get underlying coords if appropriate boolean useDefault = isUseDefaultReferenceFrame(); while (useDefault && coords instanceof ReferenceFrame) { coords = ((ReferenceFrame) coords).getCoords(); } double startTime = t0 + dt * tracePtsPerStep * (start - getStartFrame()) / clip.getStepSize(); double stepSize = 1.0 * clip.getStepSize() / tracePtsPerStep; int stepCount = (tracePtsPerStep * (end - start)) / clip.getStepSize(); ParticleModel[] models = getModels(); // prepare larger trace arrays and copy existing points into them for (ParticleModel next : models) { next.locked = false; int traceLength = next.traceX.length + stepCount; next.prevX = next.traceX; next.prevY = next.traceY; next.traceX = new double[traceLength]; next.traceY = new double[traceLength]; System.arraycopy(next.prevX, 0, next.traceX, 0, next.prevX.length); System.arraycopy(next.prevY, 0, next.traceY, 0, next.prevY.length); } for (int i = 0; i < stepCount; i++) { int stepNumber = i + 1; int frameNumber = start + (int) (stepNumber * stepSize); time = startTime + stepNumber * dt; Point2D[] points = getNextTracePositions(); if (points == null) continue; AffineTransform transform = coords.getToImageTransform(frameNumber); for (int j = 0; j < models.length; j++) { transform.transform(points[j], points[j]); // determine if point is invalid due to out of bounds boolean valid = Math.abs(points[j].getX()) < xLimit && Math.abs(points[j].getY()) < yLimit; if (!valid && !invalidWarningShown) { invalidWarningShown = true; Runnable runner = new Runnable() { // avoids deadlock? public void run() { // if (invalidWarningShown) return; JOptionPane.showMessageDialog( trackerPanel, TrackerRes.getString("ParticleModel.Dialog.Offscreen.Message1") + XML.NEW_LINE //$NON-NLS-1$ + TrackerRes.getString( "ParticleModel.Dialog.Offscreen.Message2"), //$NON-NLS-1$ TrackerRes.getString("ParticleModel.Dialog.Offscreen.Title"), // $NON-NLS-1$ JOptionPane.WARNING_MESSAGE); } }; SwingUtilities.invokeLater(runner); } models[j].traceX[models[j].prevX.length + i] = valid ? points[j].getX() : Double.NaN; models[j].traceY[models[j].prevY.length + i] = valid ? points[j].getY() : Double.NaN; if (stepNumber % tracePtsPerStep == 0) { // refresh position step saveState(frameNumber); PositionStep step = (PositionStep) models[j].getStep(frameNumber); if (step == null) { step = createPositionStep(models[j], frameNumber, 0, 0); step.setFootprint(models[j].getFootprint()); models[j].steps.setStep(frameNumber, step); } step.getPosition().setPosition(valid ? points[j] : nan); // this method is fast } } } int count = 4 + (end - start); int startUpdate = start; // step back twice to pick up possible valid derivatives if (startUpdate > clip.getStepSize()) startUpdate -= clip.getStepSize(); if (startUpdate > clip.getStepSize()) startUpdate -= clip.getStepSize(); lastValidFrame = end; for (ParticleModel next : models) { next.steps.setLength(end + 1); coords = trackerPanel.getCoords(); // get active coords // special treatment if this is the origin of current reference frame if (coords instanceof ReferenceFrame && ((ReferenceFrame) coords).getOriginTrack() == next) { // set origins of reference frame boolean prev = next.refreshing; // save refreshing value next.refreshing = true; ((ReferenceFrame) coords).setOrigins(); // then set positions to zero wrt origins for (int i = 0; i < clip.getStepCount(); i++) { int frameNumber = clip.stepToFrame(i); PositionStep step = (PositionStep) next.getStep(frameNumber); if (step == null) continue; AffineTransform transform = coords.getToImageTransform(frameNumber); next.point.setLocation(0, 0); transform.transform(next.point, next.point); step.getPosition().setPosition(next.point); // this method is fast } next.refreshing = prev; // restore refreshing value if (!refreshDerivsLater) { next.updateDerivatives(startUpdate, count); } } else if (!refreshDerivsLater) { next.updateDerivatives(startUpdate, count); } if (next.vAtOrigin) next.vTailsToOriginItem.doClick(); if (next.aAtOrigin) next.aTailsToOriginItem.doClick(); if (!refreshDerivsLater) { if (singleStep) next.support.firePropertyChange("step", null, new Integer(n)); // $NON-NLS-1$ else next.support.firePropertyChange("steps", null, null); // $NON-NLS-1$ } // erase refreshed steps for (int i = start + 1; i <= end; i++) { Step step = next.getStep(i); if (step != null) step.erase(); } next.locked = true; } trackerPanel.repaint(); } }