📄 gannotator.java
字号:
package no.geosoft.cc.graphics;import java.util.Collection;import java.util.Iterator;import no.geosoft.cc.geometry.Geometry;import no.geosoft.cc.geometry.Region;import no.geosoft.cc.geometry.Rect;/** * Layout manager for positionals. Positionals are object attached * to graphic elements by means of rendering hints. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ class GAnnotator{ private static final int MAX_ATTEMTS = 300; private static final double DLENGTH = 8.0; private final GScene scene_; private final Region region_; // Annotation region // Precomputed viewport numbers for speed private int vx0_, vy0_; private int vx1_, vy1_; private int vx2_, vy2_; private int vx3_, vy3_; // Working variable during annotation private double distance_; /** * Create annotator for the specified scene. The annotator use the * scene viewport as its canvas, and position all positional elements * of the scene inside this region. * * @param scene Scene of this annotator. */ GAnnotator (GScene scene) { region_ = new Region(); scene_ = scene; } /** * Reset this annotator. The annotator must be reset when the scene * viewport is changed. */ void reset() { region_.set (scene_.getRegion()); // Precompute some viewport numbers GViewport viewport = scene_.getViewport(); int p0[] = viewport.getP0(); // x,y int p1[] = viewport.getP1(); // x,y int p2[] = viewport.getP2(); // x,y vx0_ = p0[0]; vy0_ = p0[1]; vx1_ = p1[0]; vy1_ = p1[1]; vx2_ = p2[0]; vy2_ = p2[1]; vx3_ = vx2_ + vx1_ - vx0_; vy3_ = vy1_ + vy2_ - vy0_; } /** * Compute the x and y position of the specified positional elements * and set isVisible flag in case they are outside the screen. * After this computation is done on all nodes, the positionals can be * rendered directly by the GCanvas object. * * @param positionals Elements to position (of GPositional). */ void computePositions (Collection positionals) { // Return here if nothing to position if (positionals == null) return; int objectNo = 0; for (Iterator i = positionals.iterator(); i.hasNext(); ) { GPositional positional = (GPositional) i.next(); GSegment segment = positional.getSegment(); int positionHint = positional.getPositionHint(); // Save a copy of the old rectangle Rect oldRectangle = new Rect (positional.getRectangle()); boolean wasVisible = positional.isVisible(); if (segment.isVisible()) { int x[] = segment.getX(); int y[] = segment.getY(); int x0 = segment.getCenterX(); int y0 = segment.getCenterY(); // Compute positional size positional.computeSize(); if (positional.getRectangle().isEmpty()) { positional.setVisible (false); continue; } // Find the preferred annotation according to line position hints int pointNo = findPreferredPosition (positional, x, y, x0, y0, objectNo); // If the current point is outside the viewport move it inside if ((positionHint & GPosition.DYNAMIC) != 0 && (positionHint & GPosition.MIDDLE) == 0) { positional.setVisible (true); distance_ = 0.0; if (!scene_.getRegion().isInside (positional.getRectangle().x, positional.getRectangle().y)) pointNo = moveInsideWindow (positional, x, y, pointNo); } else { positional.setVisible (scene_.getRegion(). isInside (positional.getRectangle().x, positional.getRectangle().y)); } if (positional.isVisible()) { // Tune the positional according to point position hint adjustPosition (positional); // For a static positional we're now done if ((positionHint & GPosition.STATIC) != 0 | (positionHint & GPosition.MIDDLE) != 0) positional.setVisible (region_.isIntersecting (positional. getRectangle())); else { // GPosition.DYNAMIC and don't allow overlapping if (!positional.isAllowingOverlaps() && !region_.isInside (positional.getRectangle())) findNonOverlappingPosition (positional, x, y, pointNo); } } } // If positional was moved update damage if (!oldRectangle.equals (positional.getRectangle())) { if (wasVisible) scene_.getWindow().updateDamageArea (oldRectangle); if (positional.isVisible()) scene_.getWindow().updateDamageArea (positional.getRectangle()); if (wasVisible || positional.isVisible()) segment.getOwner().flagRegionValid (false); } // If a valid position was found update the annotation region if (positional.isVisible() && (positional.getPositionHint() & GPosition.STATIC) == 0 && !positional.isAllowingOverlaps()) region_.subtract (positional.getRectangle()); if (!positional.isLinePositional()) objectNo++; } } /** * Find the preferred position of a positional element. This is the * position as dictaed by its rendering hint and before any adjustments * are done. * * @param positional Positional element to position. * @param x X values of polyline to position according to. * @param y Y values of polyline to position according to. * @param x0 X coordinate of center of gravity of polyline * (used with rendering hint MIDDLE). * @param y0 Y coordinate of center of gravity of polyline * (used with rendering hint MIDDLE). * @param pointNo Index number of this positional on this polyline * (used when no line rendering hints are given). * @return Index in x,y of point to attach this positional to. */ private int findPreferredPosition (GPositional positional, int x[], int y[], int x0, int y0, int pointNo) { int positionHint = positional.getPositionHint(); int nPoints = x.length; if (positional.isLinePositional()) { // Find the point on the segment that the positional should attach to if ((positionHint & GPosition.LAST) != 0) { pointNo = nPoints - 1; } else if ((positionHint & GPosition.MIDDLE) != 0) { positional.getRectangle().x = x0; positional.getRectangle().y = y0; return -1; } else if ((positionHint & GPosition.TOP) != 0) { int yMin = y[0]; for (int i = 0; i < nPoints; i++) { if (y[i] < yMin) { yMin = y[i]; pointNo = i; } } } else if ((positionHint & GPosition.BOTTOM) != 0) { int yMax = y[0]; for (int i = 0; i < nPoints; i++) { if (y[i] > yMax) { yMax = y[i]; pointNo = i; } } } else if ((positionHint & GPosition.LEFT) != 0) { int xMin = x[0]; for (int i = 0; i < nPoints; i++) { if (x[i] < xMin) { xMin = x[i]; pointNo = i; } } } else if ((positionHint & GPosition.RIGHT) != 0) { int xMax = x[0]; for (int i = 0; i < nPoints; i++) { if (x[i] > xMax) { xMax = x[i]; pointNo = i; } } } } positional.getRectangle().x = x[pointNo]; positional.getRectangle().y = y[pointNo]; return pointNo; } /** * Adjsut the position of the specified positional according to * point position hint. * * @param positional Positionla to adjust. */ private void adjustPosition (GPositional positional) { int positionHint = positional.getPositionHint(); int x = positional.getRectangle().x; int y = positional.getRectangle().y; int width = positional.getRectangle().width; int height = positional.getRectangle().height; int halfWidth = (int) Math.ceil ((double) width / 2.0); int halfHeight = (int) Math.ceil ((double) height / 2.0); if ((positionHint & GPosition.NORTHWEST) != 0) { x -= width + positional.getMargin(); y -= height + positional.getMargin(); } else if ((positionHint & GPosition.NORTHEAST) != 0) { x += positional.getMargin(); y -= height + positional.getMargin(); } else if ((positionHint & GPosition.SOUTHWEST) != 0) { x -= width + positional.getMargin(); y += positional.getMargin(); } else if ((positionHint & GPosition.SOUTHEAST) != 0) { x += positional.getMargin(); y += positional.getMargin(); } else if ((positionHint & GPosition.NORTH) != 0) { x -= halfWidth; y -= height + positional.getMargin(); } else if ((positionHint & GPosition.WEST) != 0) { x -= width + positional.getMargin(); y -= halfHeight; } else if ((positionHint & GPosition.EAST) != 0) { x += positional.getMargin(); y -= halfHeight; } else if ((positionHint & GPosition.SOUTH) != 0) { x -= halfWidth; y += positional.getMargin(); } else { // GPosition.CENTER x -= halfWidth; y -= halfHeight; } positional.getRectangle().x = x; positional.getRectangle().y = y; } /** * Adjust position of the specified positional so that it doesn't overlap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -