/** * Compute the {@link Graduations} used to the ruler drawing in auto-ticks mode.. * * @return the used decimal format. */ private DecimalFormat computeUserGraduation() { /* The maximum distance corresponding to the actually displayed sprites. */ double maxSpritesDistance = 0.0; Graduations currentGraduations = rulerModel.getGraduations(); List<Double> ticks = currentGraduations.getNewValues(); DecimalFormat format = currentGraduations.getFormat(); for (double value : ticks) { Texture sprite = computeSprite(value, format); if (sprite != null) { Vector3d windowPosition = canvasProjection.project(rulerModel.getPosition(value)); Vector3d delta = projectCenterToEdge(sprite, windowTicksDelta); spritesList.add( new PositionedSprite(sprite, windowPosition.plus(windowTicksDelta.plus(delta)))); Vector3d farDelta = windowTicksDelta.plus(delta.times(2.0)); maxSpritesDistance = Math.max(maxSpritesDistance, farDelta.getNorm()); } } this.graduations = currentGraduations; this.maximalSpritesDistance = maxSpritesDistance; return format; }
/** Compute the ticks, sub-ticks data and the sub-ticks density. */ private void computeTicksData() { if (graduations != null) { ticksValue = graduations.getAllValues(); final int N = rulerModel.getSubticksNumber(); if (N < 0) { Graduations subGraduation = graduations.getSubGraduations(); while ((subGraduation != null) && (computeTicksDistance(subGraduation) < rulerModel.getMinimalSubTicksDistance())) { subGraduation = subGraduation.getAlternative(); } if (subGraduation != null) { subTicksValue = subGraduation.getAllValues(); } else { subTicksValue = new LinkedList<Double>(); } } else { subTicksValue = graduations.getSubGraduations(N); } density = getDensity(); } else { subTicksValue = new LinkedList<Double>(); ticksValue = new LinkedList<Double>(); density = 0; } }
/** * Actually perform the ruler drawing. * * @param drawingTools {@link DrawingTools} used to perform the ruler drawing. */ private synchronized void draw(DrawingTools drawingTools) { BuffersManager bufferManager = drawingTools.getCanvas().getBuffersManager(); ElementsBuffer vertices = bufferManager.createElementsBuffer(); fillVertices(vertices, rulerModel, ticksValue, subTicksValue, canvasProjection); DefaultGeometry geometry = new DefaultGeometry(); geometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE); geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS); geometry.setVertices(vertices); Appearance appearance = new Appearance(); appearance.setLineColor(rulerModel.getColor()); appearance.setLineWidth((float) rulerModel.getLineWidth()); drawingTools.getTransformationManager().useWindowCoordinate(); try { for (PositionedSprite positionedSprite : spritesList) { drawingTools.draw( positionedSprite.getSprite(), AnchorPosition.CENTER, positionedSprite.getWindowPosition()); } drawingTools.draw(geometry, appearance); } catch (SciRendererException ignored) { } drawingTools.getTransformationManager().useSceneCoordinate(); bufferManager.dispose(vertices); }
/** * Constructor. * * @param drawingTools the {@link DrawingTools} of the canvas where the ruler will be drawn. * @param rulerModel the {@link RulerModel} of the drawn ruler. */ public synchronized RulerDrawingResult drawWithResults( DrawingTools drawingTools, RulerModel rulerModel) { this.rulerModel = rulerModel; subTicksValue = new LinkedList<Double>(); ticksValue = new LinkedList<Double>(); spritesList = new LinkedList<PositionedSprite>(); canvasProjection = drawingTools.getTransformationManager().getCanvasProjection(); Vector3d windowTicksDirection = canvasProjection.projectDirection(rulerModel.getTicksDirection()); windowTicksDirection = windowTicksDirection.setZ(0); Vector3d normalizedProjectedTicksDirection = windowTicksDirection.getNormalized(); windowSubTicksDelta = normalizedProjectedTicksDirection.times(rulerModel.getSubTicksLength()); windowTicksDelta = normalizedProjectedTicksDirection.times(rulerModel.getTicksLength()); DecimalFormat format; if (rulerModel.isAutoTicks()) { format = computeAutoGraduation(); } else { format = computeUserGraduation(); } computeTicksData(); draw(drawingTools); double distRatio = computeTicksDistanceRatio(windowTicksDirection.getNorm()); return new RulerDrawingResult( format, ticksValue, subTicksValue, density, distRatio, normalizedProjectedTicksDirection); }
/** * Compute different parameters on a ruler * * @param drawingTools the {@link DrawingTools} of the canvas where the ruler will be drawn. * @param rulerModel the {@link RulerModel} of the drawn ruler. * @param canvasProjection the canvas projection. */ public synchronized RulerDrawingResult computeRuler( DrawingTools drawingTools, RulerModel rulerModel, Transformation canvasProjection) { // Same code as drawWithResults (without drawing) // Historically, computations were made when drawing and they are made before drawing. // TODO: remove drawWithResults ?? this.canvasProjection = canvasProjection; this.rulerModel = rulerModel; subTicksValue = new LinkedList<Double>(); ticksValue = new LinkedList<Double>(); spritesList = new LinkedList<PositionedSprite>(); Vector3d windowTicksDirection = canvasProjection.projectDirection(rulerModel.getTicksDirection()); windowTicksDirection = windowTicksDirection.setZ(0); Vector3d normalizedProjectedTicksDirection = windowTicksDirection.getNormalized(); windowSubTicksDelta = normalizedProjectedTicksDirection.times(rulerModel.getSubTicksLength()); windowTicksDelta = normalizedProjectedTicksDirection.times(rulerModel.getTicksLength()); DecimalFormat format; if (rulerModel.isAutoTicks()) { format = computeAutoGraduation(); } else { format = computeUserGraduation(); } computeTicksData(); double distRatio = computeTicksDistanceRatio(windowTicksDirection.getNorm()); return new RulerDrawingResult( format, ticksValue, subTicksValue, density, distRatio, normalizedProjectedTicksDirection); }
/** * Compute the {@link Graduations} used to the ruler drawing in auto-ticks mode.. * * @return the used decimal format. */ private DecimalFormat computeAutoGraduation() { /* The maximum distance corresponding to the actually displayed sprites. */ double maxSpritesDistance = 0.0; Graduations currentGraduations = rulerModel.getGraduations(); Graduations ticksGraduation = currentGraduations; DecimalFormat format = currentGraduations.getFormat(); boolean canGetMore = true; List<PositionedSprite> newSpritesList = new LinkedList<PositionedSprite>(); while (currentGraduations != null) { /* The maximum distance to any of the sprites' farthest sides at a given iteration. */ double currentMaximalSpritesDistance = 0; newSpritesList.clear(); List<Double> ticks = currentGraduations.getNewValues(); for (double value : ticks) { Texture sprite = computeSprite(value, format); Vector3d windowPosition = canvasProjection.project(rulerModel.getPosition(value)); Dimension textureSize = computeSpriteDimension(value); Vector3d delta = projectCenterToEdge(textureSize, windowTicksDelta); PositionedSprite newSprite = new PositionedSprite( sprite, textureSize, windowPosition.plus(windowTicksDelta.plus(delta))); newSpritesList.add(newSprite); Vector3d farDelta = windowTicksDelta.plus(delta.times(2.0)); currentMaximalSpritesDistance = Math.max(currentMaximalSpritesDistance, farDelta.getNorm()); } if (collide(newSpritesList, rulerModel.getMargin()) || collide(spritesList, newSpritesList, rulerModel.getMargin())) { currentGraduations = currentGraduations.getAlternative(); canGetMore = false; } else { maxSpritesDistance = Math.max(maxSpritesDistance, currentMaximalSpritesDistance); spritesList.addAll(newSpritesList); ticksGraduation = currentGraduations; if (canGetMore) { currentGraduations = currentGraduations.getMore(); } else { currentGraduations = null; } } } this.graduations = ticksGraduation; this.maximalSpritesDistance = maxSpritesDistance; return format; }
/** * Compute the ratio between windows ticks norm and the sprite distance. * * @param windowTicksNorm the windows tics norm. * @return the ratio between windows ticks norm and the sprite distance. */ private double computeTicksDistanceRatio(double windowTicksNorm) { double distRatio; if (windowTicksNorm == 0) { distRatio = 1.0; } else if (maximalSpritesDistance == 0) { distRatio = rulerModel.getSpriteDistance() / windowTicksNorm; } else { distRatio = maximalSpritesDistance / windowTicksNorm; } return distRatio; }
/** * Compute and return the minimal screen distance between two successive ticks of the given * {@link Graduations}. If the given {@link Graduations} is <code>null</code>, the returned * value is {@link Double#MAX_VALUE}. * * @param graduations the given {@link Graduations}. * @return the minimal screen distance between two successive ticks of the given {@link * Graduations}. */ private double computeTicksDistance(Graduations graduations) { double minimalDistance = Double.MAX_VALUE; if (graduations != null) { Vector3d previousProjection = null; for (double currentValue : graduations.getAllValues()) { Vector3d currentProjection = canvasProjection.project(rulerModel.getPosition(currentValue)); if (previousProjection != null) { minimalDistance = Math.min(minimalDistance, currentProjection.minus(previousProjection).getNorm2()); } previousProjection = currentProjection; } minimalDistance = Math.sqrt(minimalDistance); } return minimalDistance; }
/** * Fill a vertices buffer with the needed data to draw a ruler. * * @param verticesBuffer the {@link ElementsBuffer} to fill. * @param rulerModel the {@link RulerModel} to draw. * @param ticksValue the list of ticks. * @param subTicksValue the list of sub-ticks. * @param canvasProjection the used canvas projection. */ private void fillVertices( ElementsBuffer verticesBuffer, RulerModel rulerModel, List<Double> ticksValue, List<Double> subTicksValue, Transformation canvasProjection) { Vector3d a = rulerModel.getFirstPoint(); Vector3d b = rulerModel.getSecondPoint(); if ((a != null) && (b != null)) { int bufferSize = 2 * ticksValue.size() + 2 * subTicksValue.size(); if (rulerModel.isLineVisible()) { bufferSize += 2; } FloatBuffer data = FloatBuffer.allocate(4 * bufferSize); data.rewind(); for (double value : ticksValue) { Vector3d p = canvasProjection.project(rulerModel.getPosition(value)); data.put(p.getDataAsFloatArray(4)); data.put(p.plus(windowTicksDelta).getDataAsFloatArray(4)); } for (double value : subTicksValue) { Vector3d p = canvasProjection.project(rulerModel.getPosition(value)); data.put(p.getDataAsFloatArray(4)); data.put(p.plus(windowSubTicksDelta).getDataAsFloatArray(4)); } if (rulerModel.isLineVisible()) { data.put(canvasProjection.project(a).getDataAsFloatArray(4)); data.put(canvasProjection.project(b).getDataAsFloatArray(4)); } data.rewind(); verticesBuffer.setData(data, 4); } else { verticesBuffer.setData(new float[0], 4); } }