I am trying to allocate fixed coordinate positions for vertices using static layout. Normally we can get vertex coordinate as Point2D object using layout.transform(Vertex);
Now i wanted to initialize a layout and set the vertices at specified positions but somehow i am stuck. I read here on StackOverflow if i implement Transformer<Vertex, Point2D> interface:
Transformer<Vertex, Point2D> locationTransformer =
new Transformer<Vertex, Point2D>() {
#Override
public Point2D transform(Vertex) {
Point2D p2d = //here i calculate the position
return p2D;
}
};
I have tried this. On fixed graph it works but i have an editable graph and on it nothing happens. I was expecting if i have fixed the position in above, then whichever node i add by mouse click, it should go to the fixed position irrespective where i put it?
can you please give me some idea what could be the reason?
Or with editable graph, is it Overriding the position again somewhere?
UPDATE:
If i remove e.g these implementations from visualizaton viewer:
vv.getRenderContext().setVertexFontTransformer(fontTransfoer);
vv.getRenderContext().setVertexFillPaintTransformer(colorTransformer);
vv.getRenderContext().setVertexShapeTransformer(shapeTransformer);
It starts working, but then the nodes have default shape circular red ones. I want to completely redraw the structure that i had drawn last time. So is there something that can be done with this problem?
Related
I have a 'javafx.scene.shape.Box' with a 'javafx.scene.shape.MeshView' shown at it's coordinates.
I want to rotate this box 90-degrees using the keyboard (perhaps WASDQE, WS, QE and AD for the different axises). I also want to save the box-rotation to JSON and then be able to set that rotation again.
What I've tried (the box- and meshview-properties are bound):
box.setRotate(box.getRotate + angle); // angle being +-90 and reset on > 360 or < -360
box.setRotationAxis(Rotate.X_AXIS); // Axis depending on key pressed
This approach works for the current axis, and it works to save and load using JSON since I can set/get this value. However, with this, it seems I can not rotate all the angles, because when I change rotation-axis it forgets the previous rotation and starts from the 'default'/'starting'-rotation.
I've also tried doing it like below:
this.setRotationAxis(this.getRotationAxis().normalize().add(Rotate.X_AXIS));
This approach results with the box rotating on multiple axis, in other words, it seems to remember previous axises, but it does not rotate the axis I just added by the angle given. The box ends up tilted.
The last thing I've tried was to add the rotation as a transform:
this.getTransforms().add(new Rotate(angle, Rotate.X_AXIS));
(
also tried this with some code I found that did this with inverseDeltaTransform (where node being the box):
private void addRotate(Node node, Point3D rotationAxis, double angle) {
ObservableList<Transform> transforms = node.getTransforms();
try {
for (Transform t : transforms) {
rotationAxis = t.inverseDeltaTransform(rotationAxis);
}
} catch (NonInvertibleTransformException ex) {
throw new IllegalStateException(ex);
}
transforms.add(new Rotate(angle, rotationAxis));
}
)
This approach, however, leaves me with two problems.
Problem 1:
If i render the box, it rotates just fine, but if I render the meshview, it seems to rotate around a pivot rather then to rotate on the spot.
Problem 2:
If i add the rotation through transforms, how would I save the current rotation to JSON and then apply it again when I load it?
box.getRotationAxis() and box.getRotate() will now just show the default-values as if the box is never rotated and box.getTransforms() does not seem to make this easy.
Another question about the transforms:
The list of transforms is building up with every rotation, would I need to clear this list to avoid memory-issues and would clearing the list affect the current rotation?
I'm trying to build a logic function for my map building application that will tell me if there is an available path from one swing object to another.
Specifically I want to identify all the possible paths from one Jabel to another Jlabel.
Empty space is denoted by a white image, a wall is denoted as a blue image, player start is orange, and player finish is green.
So what I think I want to do is check each available path from the starting point. If the path ends at the goal return true, if it ends at a wall then make that the new starting path. My current Idea is to create a 2d array that populates with ints 0. When a the user changes a tile to something other than white, a corresponding spot in the array will change to 1 2 or 3 depending on what tile they placed. Then when they try to save the map the algorithm would use that 2d array to represent the map and check adjacent and linear paths.
Am I on the right track with this or is it more complicated?
I feel like this could turn out to be very slow(like n^2 or worse) if it's a complicated map because the paths can branch out. I'm thinking about using a sort of Dijkestras method for solving this, but I also don't know how exactly I would do that in swing.
There are some movement restrictions in the game as well.
You can't change directions unless you are stopped.
You can't stop unless you hit a wall or the edge of the map.
This eliminates a few options to sift through, as the number of paths become alot more limited.
Yes I think you are on the right path.. You can use something like this for collision:
In which you made a object, class Coordinate
constructor(){
block = new Coordinate[length];
path = new Coordinate[length];
for (int i=0;i<number_of_blocks;i++){
if (block[i].x==path[length_of_path].x && block[i].y==path[length_of_path].y){
//now you have a collision so go back
}
or
for (int i=0;i<number_of_blocks;i++){
if (block[i].x==path[length_of_path].x+1 && block[i].y==path[length_of_path].y){
//now you know you have a block on the right side
}
In which you have to make a object for, class Coordinate for example, to help store the coordinates.
class Coordinate {
int x,y;
Coordinate() {
x=0;
y=0;
}
Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
}
This way you can easily check if there is a collision or not and if you're out of bounds. Then you change direction adding a new coordinate to you string with the new coordinates and so on. I think this is easier then using 2d Arrays.
If you're array is out of options you go back till there is another direction possible and go that way. (You only have to save seperatly what your previous coordinates were and overwrite them while you go back).
GL
I'm trying to draw lines with Java Swing. The goal is to open an image inside the panel and draw lines on that image. When I try to draw a single line and drag the mouse, I get this behavior:
My code:
// Somewhere in the code:
imgLabel= new JLabel(new ImageIcon(buffImage)); // buffImage is a BufferedImage
...
Point point1;
Point point2;
Line2D line2d;
public void draw() {
Graphics2D g1 = this.buffImage.createGraphics();
g1.setRenderingHint(enderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g1.setColor(Color.RED);
g1.setStroke(new BasicStroke(1.5f));
if (point1 != null && point2 != null) {
g1.draw(line2d);
this.imgLabel.repaint();
}
}
class ImageMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent me) {
point1 = me.getPoint();
}
#Override
public void mouseDragged(MouseEvent me) {
point2 = me.getPoint();
line2d = new Line2D.Double(point1, point2);
draw();
}
}
The code you provide for drawing is correct. The issue here is that whenever you move your mouse cursor, the program is going to draw another line from the starting point to your current mouse position, resulting in the effect you show us (you're just forgetting to delete the old line).
To fix this, every time the mouse is moved you need to:
Draw the previous line again using XOR mode
Draw the second line.
This means you need to store the previous mouse position for when mouseDragged() is called.
I implemented something very similar using JOGL instead of Graphics, using setXORMode(Color color). This is also available for the Graphics class. You can read about the XOR mode in the Graphics class here and here.
I don't know how much complexity you're going to put on your project, but if you're anticipating more complexity I would advise using a library like JOGL. It's VERY useful.
UPDATE: Addressing overlapped lines
This is a more challenging task. First, if you're curious and want to fully understand why overlapped lines produce such an intriguing effect, I would advise you to read this.
I guess the only way is to store every line coordinates and redraw them after each new line drawing
This is a very good first approach. Keeping a data structure will all vertices and the shapes they are associated with would allow you to keep calling repaint(). You must also be aware that in doing so the intersect points will not stand out in your screen (you'll see either one line color or the other, no intermediate colors), but this should already be your intent.
Do you know what a bounding box is? You can create a bounding box for any line (or shape) which is just a rectangle that surrounds your points.
Let's assume you do in fact keep a bounding box for each line. When adding a new line, you could:
Check if the line you're about to draw intercepts any bounding boxes
If it does, repaint all lines associated with those bounding boxes
Add the new line without XOR mode
This technique is better than redrawing the entire screen because there could be an arbitrary number of lines already present, and you can write a decently efficient algorithm to check for bounding box intersections.
Note that intercepting a bounding box does not imply that there is overlapping, because there are some exceptions (e.g. parallel lines) that make this a wrong assumption. Also keep in mind that the only way to avoid seeing line intersections painted with a distinct color due to XOR mode is to draw them without XOR mode. You will have to be very careful toggling XOR mode on and off at the right times.
I found an interesting page about additional ways you could tackle this problem, you can check it here.
your problem is this part of your code
public void mouseDragged(MouseEvent me) {
point2 = me.getPoint();
line2d = new Line2D.Double(point1, point2);
draw();
specifically line2d = new Line2D.Double(point1, point2);
it's drawing a new line one the mouse is dragged.
As succinctly as I can manage: Given that I need the layout information of a node (the actual height/width of a node as rendered) to compute my animation, how can I get that information before javafx draws a frame with it?
A little bit longer explanation:
I've got a TreeItem that has child items appearing in it (at the front). What I'd like to have is an animation to cause all existing children to slide down to make room for the new item which would slide in. Each child tree-items contents are different and only known at run-time, meaning the height of each child tree item cannot be expressed as a constant.
This got me writing code along these lines:
groupController.groupTreeItem.getChildren().addListener(
new ListChangeListener<TreeItem<Node>>() {
#Override public void onChanged(Change<? extends TreeItem<Node>> c) {
while(c.next()){
if ( ! c.wasAdded()){
continue;
}
TreeItem newItem = c.getAddedSublist().get(0)
new Timeline(
new KeyFrame(
seconds(0),
new KeyValue(view.translateYProperty(), -1 * newItem.getHeight())
),
new KeyFrame(
seconds(1),
new KeyValue(view.translateYProperty(), 0)
)
);
}
}
}
);
the issue here is that as when a treeItem is added to another, its components aren't laid out by the time the invalidation event is fired, meaning newItem.view.getHeight() returns 0.
My next thought was to then have the animation performed as a reaction to both a change in the list content and a sequential change to the height property, (which got me to write some really hideous code that I'd rather not share --listeners adding listeners is not something I really want to write). This almost works, except that javaFX will draw a single frame with the height property set but without the animations translation applied. I could hack down this road further and try to work something out with opacity being toggled and jobs being enqueued for later, but I figured that this would be the path to madness.
I'm wondering if there's some pseudo-class foo or some clever use of a layout property I could use to help me here. I've been poking around at various combinations of various properties, and haven't gotten anywhere. It seems that as soon as the component has a height, it is rendered, regardless of any listeners you put in or around that height assignment.
Any help much appreciated!
have you tried, overriding this
#Override
protected void updateBounds() {
super.updateBounds();
}
I have a map that is being drawn on the screen inside a VisualizationView. I am able to zoom in and out on this map, depending on where I focused inside this view using the touch functionality.
I also toggle between zooming in and drawing on this map. When I draw an arrow on the map and switch back to zooming in. I want the arrow I drawed on the map to stay at the same spot relative to the map I am zooming in and out on. Meaning the x and y pos of this arrow have to be adjusted.
I have all the variables needed I just dont know how to solve this since its math related.
Can someone explain to me how I can solve this math wise. I tried looking on the internet but I could not find a good explanation. Also the map resolution on the Tablet is always 576 x 576.
public void onZoom(final double focusX, final double focusY,
final double factor) {
//pseudocode
Triangle.x = ..
Triangle.y = ..
Triangle.repaint();
//peusocode
}
The code for the zooming is as following straight from the Library.
public void zoom(double focusX, double focusY, double factor) {
synchronized (mutex) {
Transform focus = Transform.translation(toMetricCoordinates((int) focusX, (int) focusY));
double zoom = RosMath.clamp(getZoom() * factor, MINIMUM_ZOOM, MAXIMUM_ZOOM) / getZoom();
transform = transform.multiply(focus).scale(zoom).multiply(focus.invert());
}
}
I hope someone can explain the math behind solving this.
I'm not directly familiar with the library you're using, but to move the location of the arrow (triangle) to its new location you should apply the same transform to it as you do to the map.
Think of it this way: Before zooming, the location of the arrow (the center or head of the arrow, however you define "location") and the point on the map it's pointing to have the same coordinates. After zooming, the point on the map will have moved to a new location and you want the arrow to move to that same new location, thus you need to use the same transform. Like I said, I'm not familiar with the library you're using so I can't tell you exactly how to do that, but that's where you want to be.
Note, however, that you only want to transform one point of the arrow/triangle and draw the other points relative to it. If you transform all 3 you'll end up with the arrow getting larger and smaller as you zoom in and out (which I assume you don't want).