public GraphicLayoutInfo calculateOffsetAndScale(Dimension size) { boolean considerAuxVertices = options.getOption(OptionsEnum.considerAuxVertices).getBool(); Position minPos = Position.min(graph.getVertices(), true, considerAuxVertices); Position maxPos = Position.max(graph.getVertices(), true, considerAuxVertices); float width; float height; final int OFFSET_FROM_BORDERS = calculateVertexRadius(options.graph.getMaxDegree()); if (options.getOption(OptionsEnum.stretchGraphToBounds).getBool()) { width = maxPos.x - minPos.x; height = maxPos.y - minPos.y; } else { width = Position.width(maxPos, minPos); height = width; } if (width == 0) { width = 1; } if (height == 0) { height = 1; } int sizeX = (int) size.getWidth(); int sizeY = (int) size.getHeight(); Position offset = new Position(); offset.x = Position.add(Position.mult(minPos, -1), 0.05f * width).x; offset.y = Position.add(Position.mult(minPos, -1), 0.05f * height).y; // Flip y-coordinate. Position scale = new Position(1, -1, 1); scale.x *= (0.9f * sizeX / width); if (options.getOption(OptionsEnum.stretchGraphToBounds).getBool()) { scale.y *= (0.9f * sizeY / (height + OFFSET_FROM_BORDERS)); } else { scale.y *= (0.9f * sizeY / height); } Position maxPosScaled = Position.add(maxPos, offset); maxPosScaled.mult(scale); if (options.getOption(OptionsEnum.stretchGraphToBounds).getBool()) { sizeY = (int) Math.abs(maxPosScaled.y) + OFFSET_FROM_BORDERS; } else { // do nothing } return new GraphicLayoutInfo(width, height, sizeY, offset, scale, maxPosScaled); }
public void writeGraphicsLayout( List<GraphVertex> vertices, List<GraphEdge> edges, Dimension size) { GraphicLayoutInfo graphicLayoutInfo = calculateOffsetAndScale(size); int sizeX = (int) size.getWidth(); int sizeY = (int) size.getHeight(); // Draw the edges. for (GraphEdge edge : edges) { if (options.getOption(OptionsEnum.showEdges).getBool() || edge.showEdge()) { // Only draw the edge if it and both of its incident vertices are visible if ((edge.getSource().isShowVertex() || edge.getTarget().isShowVertex()) && !edge.isAuxiliaryEdge()) { Position sourcePos = graphicLayoutInfo.mapToOriginal(edge.getSource().getPosition()); Position targetPos = graphicLayoutInfo.mapToOriginal(edge.getTarget().getPosition()); writeEdge( edge, (int) sourcePos.x, (int) sourcePos.y, (int) sourcePos.z, (int) targetPos.x, (int) targetPos.y, (int) targetPos.z); } } } // Draw the vertices. // First draw the vertices that are not annotated (put them to background). for (GraphVertex vertex : vertices) { if (vertex.isShowVertex() && !(options.getOption(OptionsEnum.hideSource).getBool() && vertex.isSource()) && !vertex.isAuxiliary() && !vertex.isShowName()) { calculateAndWriteVertex(sizeX, sizeY, graphicLayoutInfo, vertex); } } // Draw the annotated vertices. // Second draw the annotated vertices (put them to foreground). for (GraphVertex vertex : vertices) { if (vertex.isShowVertex() && !(options.getOption(OptionsEnum.hideSource).getBool() && vertex.isSource()) && !vertex.isAuxiliary() && vertex.isShowName()) { calculateAndWriteVertex(sizeX, sizeY, graphicLayoutInfo, vertex); } } }
private void calculateAndWriteVertex( int sizeX, int sizeY, GraphicLayoutInfo graphicLayoutInfo, GraphVertex vertex) { Position position = graphicLayoutInfo.mapToOriginal(vertex.getPosition()); // Determine color for vertex. Color color = vertex.getColor(); if (options.getOption(OptionsEnum.depDegreeColor).getBool()) { float redValue = vertex.getDegreeOut() / graph.getMaxOutdegree(); color = new Color(redValue, 1 - redValue, 0); } if (vertex.getShape() == Shape.FIXED_SIZE_BOX) { int radius = 2; writeVertex(vertex, (int) position.x, (int) position.y, (int) position.z, radius, color); } else if (vertex.getShape() == Shape.FILLER_RECT) { int width = Math.max(1, Math.round(sizeX / graphicLayoutInfo.getWidth())); int height = Math.max(1, Math.round(sizeY / graphicLayoutInfo.getHeight())); writeVertex( vertex, (int) position.x, (int) position.y, (int) position.z, width, height, color); } else { int radius = calculateVertexRadius(vertex.getDegree()); writeVertex(vertex, (int) position.x, (int) position.y, (int) position.z, radius, color); } }
/** Calculates the two angled lines that form the arrow head. */ protected int[] paintArrow(int x0, int y0, int x1, int y1) { int[] arrowPoints = new int[8]; double angleFactor = 0.5; double tipLocPercentage = 0.9 - options.getOption(OptionsEnum.minVert).getFloat() * 0.02; double xMid = x0 + tipLocPercentage * (x1 - x0); double yMid = y0 + tipLocPercentage * (y1 - y0); double deltaX = xMid - x0; double deltaY = yMid - y0; deltaX *= angleFactor; deltaY *= angleFactor; double diaLength = (Math.sqrt(deltaX * deltaX + deltaY * deltaY) * Math.sqrt(2)); // (deltaY, -deltaX) double x2 = (x0 + deltaY - xMid) / diaLength; double y2 = (y0 - deltaX - yMid) / diaLength; // (-deltaY, deltaX) double x3 = (x0 - deltaY - xMid) / diaLength; double y3 = (y0 + deltaX - yMid) / diaLength; double arrowTipSizeFactor = 5; double xt2 = xMid + arrowTipSizeFactor * x2; double yt2 = yMid + arrowTipSizeFactor * y2; double xt3 = xMid + arrowTipSizeFactor * x3; double yt3 = yMid + arrowTipSizeFactor * y3; arrowPoints[0] = (int) Math.round(xMid); arrowPoints[1] = (int) Math.round(yMid); arrowPoints[2] = (int) Math.round(xt2); arrowPoints[3] = (int) Math.round(yt2); arrowPoints[4] = (int) Math.round(xMid); arrowPoints[5] = (int) Math.round(yMid); arrowPoints[6] = (int) Math.round(xt3); arrowPoints[7] = (int) Math.round(yt3); return arrowPoints; }
@Override public void loadOptions() { scaleTextField.setValue(new Float(options.getOption(OptionsEnum.scalePos).getFloat())); dimensionsSpinner.setValue(options.getOption(OptionsEnum.dim).getInt()); numOfIterationsSpinner.setValue(options.getOption(OptionsEnum.iter).getInt()); autoStopIteratingCheckBox.setSelected( options.getOption(OptionsEnum.autoStopIterating).getBool()); initialLayoutTextField.setText(options.getOption(OptionsEnum.initLayout).getString()); attractionExponentTextField.setValue(new Float(options.attrExponent)); gravitationTextField.setValue(new Float(options.gravitation)); repulsionExponentTextField.setValue(new Float(options.repuExponent)); weightedCheckbox.setSelected(!options.noWeight); animationCheckBox.setSelected(options.getOption(OptionsEnum.anim).getBool()); if (options.vertRepu) { repulsionTypeTextField.setSelectedIndex(1); } else { repulsionTypeTextField.setSelectedIndex(0); } }
@Override public void applyOptions() { options.getOption(OptionsEnum.dim).set(((Integer) dimensionsSpinner.getValue()).intValue()); options .getOption(OptionsEnum.iter) .set(Integer.parseInt(this.numOfIterationsSpinner.getValue().toString())); options.getOption(OptionsEnum.autoStopIterating).set(autoStopIteratingCheckBox.isSelected()); options.getOption(OptionsEnum.initLayout).set(initialLayoutTextField.getText()); options.attrExponent = (Float) attractionExponentTextField.getValue(); options.repuExponent = (Float) repulsionExponentTextField.getValue(); options.gravitation = ((Number) gravitationTextField.getValue()).floatValue(); options.vertRepu = (repulsionTypeTextField.getSelectedIndex() == 1); options.noWeight = !weightedCheckbox.isSelected(); options.getOption(OptionsEnum.scalePos).set((Float) scaleTextField.getValue()); options.getOption(OptionsEnum.anim).set(animationCheckBox.isSelected()); }
private int calculateVertexRadius(float degree) { return (int) Math.max( Math.pow(degree, 0.5) * options.getOption(OptionsEnum.minVert).getFloat(), options.getOption(OptionsEnum.minVert).getFloat()); }