So I just started using Apache PDFBox (0.7.3) in one of my projects to write to PDF. I want to draw a line across the whole page, which according to the docs and many examples I have seen, I should be able to do by calling the drawLine() method from my PDPageContentStream. However, in Eclipse I only see two drawImage methods and a drawString method. Does anyone know what I should do to fix this? Is the drawLine method deprecated or something?
In PDPageContentStream I see:
/**
* Draw a line on the page using the current non stroking color and the current line width.
*
* #param xStart The start x coordinate.
* #param yStart The start y coordinate.
* #param xEnd The end x coordinate.
* #param yEnd The end y coordinate.
* #throws IOException If there is an error while drawing on the screen.
*/
public void drawLine(float xStart, float yStart, float xEnd, float yEnd) throws IOException
{
if (inTextMode)
{
throw new IOException("Error: drawLine is not allowed within a text block.");
}
addLine(xStart, yStart, xEnd, yEnd);
// stroke
stroke();
}
Thus, either your PDFBox copy is outdated or your eclipse does not show existing methods.
I use eclipse Kepler here and see the method all right.
It is located between addLine and addPolygon in the source, far away from drawImage or drawString. If you are searching in the outline, you maybe should activate sort-by-name there.
Related
I'm working on a project with Processing that requires the ability to determine whether or not the mouse is inside of a circle. Therefore, I need to obtain the position of the circle and the position of the mouse. However, the position of the circle has been modified using matrix functions such as translate and scale. For example:
float circle_x;
float circle_y;
float circle_radius;
void setup() {
circle_x = 10.0;
circle_y = 17.0;
circle_radius = 15.0;
}
void draw() {
pushMatrix();
/* ... arbitrary number of calls to modify the matrix ... */
translate(THING, THING);
scale(THING);
translate(THING);
/* ... */
/* draw the circle */
ellipse(circle_x, circle_y, circle_radius, circle_radius);
/* now I want to detect whether or not my mouse is inside of the
circle. In order to do that, I need to modify the coordinates
of the mouse in the same fashion as circle_x and circle_y. I'm
hoping to do something like this: */
float world_x = screenToWorld_X(mouseX);
float world_y = screenToWorld_Y(mouseY);
/* ... check if [world_x, world_y] is inside the circle ... */
popMatrix();
}
Is there any way to do this in Processing? I was looking at the documentation but I couldn't seem to find any functions. If not, how can I achieve my goal?
Thanks.
Check out the coordinates section of the reference.
Specifically, you're looking for the modelX() and modelY() functions. Or you could use the screenX() and screenY() functions to go the other way and convert your world coordinates into screen coordinates.
I'm using the ARToolkit for android and try to write a text over the detected marker. I want to do this using a simple TextView. So I'm only using ARToolkit to find the marker.
But how can I find out where in my camera-preview the marker is right no (I need the coordinates), so I can but the TextView over the marker?
Thanks in advance !
Both comments are correct, ARToolkit returns both a Projection Matrix and a Transformation Matrix. Both are designed to be used with OpenGL, not with a standard Android view. The projection matrix is to be applied to the camera and the transformation one is to be applied to the object (pose matrix)
If you only want to display text, I recommend you to use the Unity plugin and then use the Unity UI components to add a canvas and a text attached to the marker. Those components are already designed to be 3D objects (if you go that way, remember to set the canvas to "World Space".
The other options you have are:
a) Render the text into a texture and draw it on a Quad, you can do that based on the example that has a cube.
b) Do some matrix calculations using both matrix and the apply transformations to the TextView on position and rotation using a transformation Matrix (the Android class). Although is possible, the math involved is rather complex. If you want it to just float looking at the camera, setTranslationX, Y and Z should be enough.
c) Link a 3D engine with text rendering capability to ARToolkit. I've done that with jPCT-AE. While this works, it takes quite a lot of work. I plan to write about it soon.
There is another option to detect the markers corner points.
It will require some changes to the wrapper code and recompiling the Android binaries.
Fork or clone the artoolkit5 github repository and make the following changes:
Add an entry to ARMarker.h
float cornerPoints[8];
In ARMarkerSquare.cpp make a change in the updateWithDetectedMarkers method just after the code where a marker has been determined visible, update the cornerPoints:
// Consider marker visible if a match was found.
if (k != -1) {
visible = true;
m_cf = markerInfo[k].cf;
for (int c = 0; c < 4; c++) {
cornerPoints[c*2] = markerInfo[k].vertex[c][0];
cornerPoints[c*2 + 1] = markerInfo[k].vertex[c][1];
}
Add a new method ARToolKitWrapperExportedAPI.cpp to retrieve the corner points:
EXPORT_API bool arwQueryMarkerCornerPoints(int markerUID, float points[8])
{
ARMarker *marker;
if (!gARTK) return false;
if (!(marker = gARTK->findMarker(markerUID))) {
gARTK->logv(AR_LOG_LEVEL_ERROR, "arwQueryMarkerCornerPoints(): Couldn't locate marker with UID %d.", markerUID);
return false;
}
for (int i = 0; i < 8; i++) points[i] = (float)marker->cornerPoints[i];
return marker->visible;
}
And add the JNI definition for that:
JNIEXPORT jfloatArray JNICALL JNIFUNCTION(arwQueryMarkerCornerPoints(JNIEnv *env, jobject obj, jint markerUID))
{
float trans[8];
if (arwQueryMarkerCornerPoints(markerUID, trans)) return glArrayToJava(env, trans, 8);
return NULL;
}
After all that I recompile the ARWrapper shared objects in the android directory with the build.sh script and used these new shared objects.
In the he NativeInterface.java add the following method:
/**
* Retrieves the corner points for the specified marker
*
* #param markerUID The unique identifier (UID) of the marker to check
* #return A float array of size 8 containing the corner points starting at top left (x,y) top right, bottom right, bottom left.
* So
*/
public static native float[] arwQueryMarkerCornerPoints(int markerUID);
And finally add the method to ARToolKit.java as well:
/**
* Retrieves the corner points for the specified marker
*
* #param markerUID The unique identifier (UID) of the marker to check
* #return A float array of size 8 containing the corner points starting at top left (x,y) top right, bottom right, bottom left.
*
*/
public float[] arwQueryMarkerCornerPoints(int markerUID) {
if (!initedNative) return null;
return NativeInterface.arwQueryMarkerCornerPoints(markerUID);
}
See also:
https://archive.artoolkit.org/community/forums/viewtopic.php?f=26&t=16099
The changes can be seen seen in this fork as well: https://github.com/ekkelenkamp/artoolkit5/tree/marker_corner_points
Documentation can sometimes reduce the readability of code.
Instead of
/**
* The X axis.
*/
int x;
/**
* The Y axis.
*/
int y;
/**
* The Z axis.
*/
int z;
I'd rather prefer to have
int x; /** The X axis */
int y; /** The Y axis */
int z; /** The Z axis */
Is there a way in Java to have the comments on the right of e. g. a variable declaration? I've seen it work in C by using the "<" character, but haven't seen it in Java yet. Java is already in Version 8 and I'm wondering why it still isn't possible. Or is it?
Doc Comments work only once. They could be anywhere in the code and many times but only first one is extracted by Javadoc tool. The rest is simple ignored.
I encountered a slight problem with my game's rendering system when I tried to scale certain objects. I think it must be the way I map objects with logical coordinates to graphical ones on the screen.
Renderable
/**
* Retrieve the image representing the object that should be rendered.
* #return The image sprite representing the object.
*/
public Texture getSprite();
/**
* Retrieve the x-coordinate where the object should be rendered.
* #return The x-coordinate of the object.
*/
public float getScreenX();
/**
* Retrieve the y-coordinate where the object should be rendered.
* #return The y-coordinate of the object.
*/
public float getScreenY();
Texture
......
......
/**
* Retrieve the width of the texture.
* #return The width of the texture.
*/
public int getWidth();
/**
* Retrieve the height of the texture.
* #return The height of the texture.
*/
public int getHeight();
......
......
This system works perfectly when I draw stuff like interfaces etc, which have no logical coordinates in my game world.
Let's take a look at an object that have logical coordinates and see how I map the coordinates to graphical ones and thus causing a problem when I scale the texture when drawing.
Tile
#Override
public float getScreenX() {
return x * width;
}
#Override
public float getScreenY() {
return y * height;
}
Let's say the size of the texture for any tile is 16*16 but for some reason I want to draw it at 32*32. This will cause a problem since the tile's graphical x- and y-coordinate messes up.
Note: I know that I can fix this by allowing the user to set a scale when loading the image into the system but I want it to be more flexible.
TL;DR: How can I accomplish a better mapping between logical coordinates in the game world to graphical ones while still being able to scale when I want to? There should be a better way to map instead of letting the logical objects be in charge of their graphical coordinates.
So I'm trying to figure out how to implement a method of selecting lines or edges in a drawing area but my math is a bit lacking. This is what I got so far:
A collection of lines, each line has two end points (one to start and one to end the line)
The lines are drawn correctly on a canvas
Mouse clicks events are received when clicking the canvas, so I can get the x and y coordinate of the mouse pointer
I know I can iterate through the list of lines, but I have no idea how to construct an algorithm to select a line by a given coordinate (i.e. the mouse click). Anyone got any ideas or point me to the right direction?
// import java.awt.Point
public Line selectLine(Point mousePoint) {
for (Line l : getLines()) {
Point start = l.getStart();
Point end = l.getEnd();
if (canSelect(start, end, mousePoint)) {
return l; // found line!
}
}
return null; // could not find line at mousePoint
}
public boolean canSelect(Point start, Point end, Point selectAt) {
// How do I do this?
return false;
}
Best way to do this is to use the intersects method of the line. Like another user mentioned, you need to have a buffer area around where they clicked. So create a rectangle centered around your mouse coordinate, then test that rectangle for intersection with your line. Here's some code that should work (don't have a compiler or anything, but should be easily modifiable)
// Width and height of rectangular region around mouse
// pointer to use for hit detection on lines
private static final int HIT_BOX_SIZE = 2;
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Line2D clickedLine = getClickedLine(x, y);
}
/**
* Returns the first line in the collection of lines that
* is close enough to where the user clicked, or null if
* no such line exists
*
*/
public Line2D getClickedLine(int x, int y) {
int boxX = x - HIT_BOX_SIZE / 2;
int boxY = y - HIT_BOX_SIZE / 2;
int width = HIT_BOX_SIZE;
int height = HIT_BOX_SIZE;
for (Line2D line : getLines()) {
if (line.intersects(boxX, boxY, width, height) {
return line;
}
}
return null;
}
Well, first off, since a mathematical line has no width it's going to be very difficult for a user to click exactly ON the line. As such, your best bet is to come up with some reasonable buffer (like 1 or 2 pixels or if your line graphically has a width use that) and calculate the distance from the point of the mouse click to the line. If the distance falls within your buffer then select the line. If you fall within that buffer for multiple lines, select the one that came closest.
Line maths here:
http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
Shortest distance between a point and a line segment
If you use the 2D api then this is already taken care of.
You can use Line2D.Double class to represent the lines. The Line2D.Double class has a contains() method that tells you if a Point is onthe line or not.
Sorry, mathematics are still required... This is from java.awt.geom.Line2D:
public boolean contains(double x,
double y)
Tests if a specified coordinate is inside the boundary of this Line2D.
This method is required to implement
the Shape interface, but in the case
of Line2D objects it always returns
false since a line contains no area.
Specified by:
contains in interface Shape
Parameters:
x - the X coordinate of the specified point to be tested
y - the Y coordinate of the specified point to be tested
Returns:
false because a Line2D contains no area.
Since:
1.2
I recommend Tojis answer