I made a dial chart Using JFreeChart. I was wondering if it was possible to make the indicators thicker. The code I am using to make them now are:
StandardDialRange standarddialrange;
StandardDialRange standarddialrange2;
StandardDialRange standarddialrange3;
if(isPercentageIV==true){
standarddialrange = new StandardDialRange(90D, 100D, Color.GREEN);
standarddialrange2 = new StandardDialRange(60D, 90D, Color.orange);
standarddialrange3 = new StandardDialRange(0D, 60D, Color.RED);
}
else{
standarddialrange = new StandardDialRange(.9*goal*dialScale, goal*dialScale, Color.GREEN);
standarddialrange2 = new StandardDialRange(.6*goal*dialScale, .9*goal*dialScale, Color.orange);
standarddialrange3 = new StandardDialRange(0, .6*goal*dialScale, Color.RED);
}
// Sets the scale/radius of all the indicators.
standarddialrange.setScaleIndex(0);
standarddialrange.setInnerRadius(0.58999999999999997D);
standarddialrange.setOuterRadius(0.58999999999999997D);
dialplot.addLayer(standarddialrange);
standarddialrange2.setScaleIndex(0);
standarddialrange2.setInnerRadius(0.58999999999999997D);
standarddialrange2.setOuterRadius(0.58999999999999997D);
dialplot.addLayer(standarddialrange2);
standarddialrange3.setScaleIndex(0);
standarddialrange3.setInnerRadius(0.58999999999999997D);
standarddialrange3.setOuterRadius(0.58999999999999997D);
dialplot.addLayer(standarddialrange3);
I tried looking online and I could not figure out how to make it thicker. The way they are now makes them kind of hard to see on a display from far away. I tried changing the outer radius but it just made it so their were two thin lines, instead of one big thick one.
Override the draw() method of StandardDialRange and specify your preferred Stroke; I've used 4.0f in the example below. You'll need to recapitulate the existing code, using the public accessors as required.
plot.addLayer(new StandardDialRange(3 * maximumValue / 4, maximumValue, Color.red) {
#Override
public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame, Rectangle2D view) {
…
g2.setPaint(this.getPaint());
g2.setStroke(new BasicStroke(4.0f));
g2.draw(arcInner);
g2.draw(arcOuter);
}
});
Related
I have created an audio visualizer using the default renderer in Processing 3, now I want to implement an independent spinning 3D cube (that uses P3D) within the audio visualizer (which was created in the default renderer). Here is the code for the 3D cube:
import processing.opengl.*;
float y = 0.1;
float x = 0.1;
float z = 0.1;
void setup()
{
size(800,600,P3D);
smooth();
}
void draw()
{
translate(400,300,0);
rotateX(x);
rotateY(y);
rotateZ(z);
background(255);
fill(255,228,225);
box(200);
x += random(.1);
y += random(.1);
z += random(.1);
}
Here's a snippet from the visualizer that pertains to 3D cube:
void setup()
{
size(800, 600);
//fullScreen(2);
minim = new Minim(this);
player = minim.loadFile("/Users/samuel/Desktop/GT.mp3");
meta = player.getMetaData();
beat = new BeatDetect();
player.loop();
fft = new FFT(player.bufferSize(), player.sampleRate());
fft.logAverages(60, 7);
noStroke();
w = width/fft.avgSize();
player.play();
background(0);
smooth();
}
Ultimately, I'm just curious if I can integrate a 3D object without changing the size() of the visualizer to P3D.
You can use the createGraphics() function to create a renderer, and you can pass P3D into that renderer to allow drawing in 3D.
However, you can't do that if your sketch is using the default renderer. You have to use either P2D or P3D in your main renderer to be able to use P3D in any createGraphics() renderers. From the reference:
It's important to consider the renderer used with createGraphics() in relation to the main renderer specified in size(). For example, it's only possible to use P2D or P3D with createGraphics() when one of them is defined in size(). Unlike Processing 1.0, P2D and P3D use OpenGL for drawing, and when using an OpenGL renderer it's necessary for the main drawing surface to be OpenGL-based. If P2D or P3D are used as the renderer in size(), then any of the options can be used with createGraphics(). If the default renderer is used in size(), then only the default or PDF can be used with createGraphics().
Here's a little example that uses a P2D renderer as the main renderer and P3D as a sub-renderer:
PGraphics pg;
void setup() {
size(200, 200, P2D);
pg = createGraphics(100, 100, P3D);
}
void draw() {
pg.beginDraw();
pg.background(0);
pg.noStroke();
pg.translate(pg.width*0.5, pg.height*0.5);
pg.lights();
pg.sphere(25);
pg.endDraw();
background(0, 0, 255);
image(pg, 50, 50);
}
I have met some problem for integration the JPCT-AE with ARNative of ARToolkit's Project.
Purpose:
using jpct-ae to rendering model basic on ARToolkit;
Status :
i can render a model on the screen behind the preview data;
however, the model could no shown in correct position;
i do not know how the using the ProjectionMatrix from ARToolkit for JPCT-AE.
My code was shown belown:
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
ARNativeActivity.nativeSurfaceCreated();
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
ARNativeActivity.nativeSurfaceChanged(width, height);
glViewport(0, 0, width, height);
fb = new FrameBuffer( width, height); // OpenGL ES 1.x constructor
world = new World();
world.setAmbientLight(20, 20, 20);
sun = new Light(world);
sun.setIntensity(250, 250, 250);
loadOBJ("cube.obj" , "cube.mtl" , "cube");
world.addObject(cubeColor);
cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cubeColor.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(cubeColor.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
}
public void onDrawFrame(GL10 unused) {
glClear(GL_COLOR_BUFFER_BIT);
ARNativeActivity.nativeDrawFrame();
float[] projection = ARNativeActivity.getProjectMatrix();
Matrix projMatrix = new Matrix();
projMatrix.setDump(projection);
projMatrix.transformToGL();
SimpleVector translation = projMatrix.getTranslation();
SimpleVector dir = projMatrix.getZAxis();
SimpleVector up = projMatrix.getYAxis();
cam.setPosition(translation);
cam.setOrientation(dir, up);
world.renderScene(fb);
world.draw(fb);
fb.display();
}
I think this question is pretty similar to a newer one you made: Rendering a model basic on JPCT-AE with ARToolkit in Android. It will most likely be duplicated. Anyway, I have still not enough privileges to mark it as duplicated, so I reference to the other and try to answer the slight differences. The only difference I can see is that here you still are not using the transformation matrix given by the artoolkit. You must get it by calling
ARNativeActivity.getTransformationM()
and put it in a JPCT matrix:
transformM.setIdentity();
transformM .setDump(ARNativeActivity.getTransformationM());
transformM .transformToGL();
As told, is already on the other question, so I suggest all users going there for a more complete answer and external references.
I can change the color of the font like this
LabelStyle style1 = new LabelStyle(..some font...,
Color.valueOf("FF4500")
);
label.setStyle(style1);
but how do I change the background?
right now the background is the same as the background of whole screen which is set in
render method lke this
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(
1.000f, 0.980f, 0.941f
,1);
Label label = new Label(labelText, skin);
Pixmap labelColor = new Pixmap(labelWidth, labelHeight, Pixmap.Format.RGB888);
labelColor.setColor(<your-color-goes-here>);
labelColor.fill();
label.getStyle().background = new Image(new Texture(labelColor)).getDrawable();
Basically, use the getDrawable() function of the Image class to assign the color of your Label's LabelStyles' background Drawable.
This is the simplest workaround I've been able to come up with and, frankly, it's just silly that there is no setBackground() in the Label class.
Actually, maybe the easiest fix is to hack the Label class and add a setBackground() method to it.
[Edit] Be sure to dispose of Pixmaps when you are done with them; i.e. labelColor.dispose();
[Update] #Mitrakov Artem made a good point: The above solution will affect all instances of this LabelStyle. If that's not what you want you can create a new LabelStyle, use the above method on it, then save it to the Label. Quoting Artem: "So I would recommend to create a new style (LabelStyle style = new LabelStyle(label.getStyle());), change its background and then apply it to the label (label.setStyle(style);)"
Actually you do not change the background of the Lable like that. You did just change the clearcolour. Guess you know that.
To change the background you need to change the background at the style of the label. To do so i'd recommend to use a simple NinePatch as background, (can be a square! if its white you can change the colour of the ninepatch and the background colour changes!)
NinePatch temp = new NinePatch(new Texture(....), 10, 10, 10, 10); //edges
For more information about ninepatch take a look here libgdx wiki ninepatch
You need to add that ninepatch to an Skin objekt. For example like this
Skin skin = new Skin();
skin.add("background",temp)
After that you can get a drawable from the skin that you can set as background of the LabelStyle.
style1.background = skin.getDrawable("background");
see libgdx API LabelStyle
You can also use a simple bitmap but that does get scaled to the label size which causes in most of the cases deformation. A Ninepatch can be scaled without having deformation.
If you need a quick and easy solution, you can use the snippet below. It doesn't work well with multiline text because it doesn't take the text width per line into account.
Anyway, the background is automatically adjusted to the width and height of the label widget (i.e. if your text changes).
private Label label = new Label("text", createLabelStyleWithBackground());
private LabelStyle createLabelStyleWithBackground() {
LabelStyle labelStyle = new LabelStyle();
labelStyle.font = new BitmapFont();
labelStyle.fontColor = Color.WHITE;
labelStyle.background = createBackground();
return labelStyle;
}
private Drawable createBackground() {
Pixmap labelColor = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
Color color = new Color(Color.GRAY);
color.a = 0.75f;
labelColor.setColor(color);
labelColor.fill();
Texture texture = new Texture(labelColor);
return new BaseDrawable() {
#Override
public void draw(Batch batch, float x, float y, float width, float height) {
GlyphLayout layout = label.getGlyphLayout();
x = label.getX();
y = label.getY() - (layout.height + 15) / 2; // +15 is some space
batch.draw(texture, x, y, layout.width, layout.height + 15);
}
};
}
here is an example with a multiline label
I have created a Chart shows Questions (X) / Time (Y) answered during a test.
You can see the first question here for details.
But now I need to show the chart bullet values correctly, at the moment shows the milliseconds value but i need to show the custom hh:mm:ss value like I've done with the Y-Axis label and somehow customize the Y-Axis area to show the full values correctly.
Below is a screenshot of how the chart looks like now.
[EDIT]
With Dan's help I almost got what I want. It's just a little problem.
Check in the screenshot below where the chart values now appearing.
I updated to 1.1.0 from the AChartEngine repository.
addNotations is on the TimeSeries objects. I copy paste my code below where adding data to my TimeSeries instance.
myQuestionsTimeSeries.add(i, DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()));
xyMultipleSeriesRenderer.addYTextLabel(DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()),
String.valueOf(answer.getEstimatedAnswerTime()));
myQuestionsTimeSeries.addAnnotation(String.valueOf(answer.getEstimatedAnswerTime()), i,
DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()));
The code results to this Chart:
[EDIT]
This is basically the whole class:
private void initQuestionsTimeChart() {
xyMultipleSeriesDataset = new XYMultipleSeriesDataset();
xyMultipleSeriesRenderer = new XYMultipleSeriesRenderer();
questionsTimeChart = ChartFactory.getLineChartView(getActivity(), xyMultipleSeriesDataset, xyMultipleSeriesRenderer);
rootView.addView(questionsTimeChart);
initSeriesData();
}
private void initSeriesData() {
createMyQuestionsSeries();
addSeriesAndRenderer(myQuestionsTimeSeries, myQuestionsRenderer);
xyMultipleSeriesRenderer.setYTitle("Questions Time");
xyMultipleSeriesRenderer.setXTitle("Questions Number");
xyMultipleSeriesRenderer.setMarginsColor(Color.argb(0, 255, 255, 255));
xyMultipleSeriesRenderer.setAxesColor(Color.BLACK);
xyMultipleSeriesRenderer.setLabelsColor(Color.BLACK);
xyMultipleSeriesRenderer.setXLabelsColor(Color.BLACK);
xyMultipleSeriesRenderer.setYLabelsColor(0, Color.BLACK);
xyMultipleSeriesRenderer.setAxisTitleTextSize(16);
xyMultipleSeriesRenderer.setLabelsTextSize(15);
xyMultipleSeriesRenderer.setYLabelsAlign(Paint.Align.RIGHT);
xyMultipleSeriesRenderer.setSelectableBuffer(20);
xyMultipleSeriesRenderer.setYLabels(0);
xyMultipleSeriesRenderer.setMargins(new int[]{ 80, 80, 80, 80 });
}
private void addSeriesAndRenderer(XYSeries series, XYSeriesRenderer renderer) {
xyMultipleSeriesDataset.addSeries(series);
xyMultipleSeriesRenderer.addSeriesRenderer(renderer);
}
private void createMyQuestionsSeries() {
myQuestionsTimeSeries = new TimeSeries("My Questions/Time");
myQuestionsRenderer = new XYSeriesRenderer();
myQuestionsRenderer.setColor(Color.BLUE);
myQuestionsRenderer.setLineWidth(3f);
myQuestionsRenderer.setPointStyle(PointStyle.CIRCLE);
myQuestionsRenderer.setFillPoints(true);
myQuestionsRenderer.setChartValuesSpacing(10f);
}
private void fillData() {
int i = 0;
for (Answer answer : getAnswers()) {
i++;
if (answer.getEstimatedAnswerTime() != null) {
myQuestionsTimeSeries.add(i, DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()));
xyMultipleSeriesRenderer.addYTextLabel(DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()),
String.valueOf(answer.getEstimatedAnswerTime()));
myQuestionsTimeSeries.addAnnotation(String.valueOf(answer.getEstimatedAnswerTime()), i,
DateTimeHelper.getMillisFromTime(answer.getEstimatedAnswerTime()));
}
}
}
Thank you in advance!
First of all, hide the chart values:
renderer.setDisplayChartValues(false);
Then, for each chart value, add an annotation:
renderer.addAnnotation("text", x, y);
For the Y axis labels to be visible, just align them to LEFT:
renderer.setYLabelsAlign(Align.LEFT);
Or you can increase the margins:
renderer.setMargins(margins);
Make sure you are using the latest ACE build available here.
I'm having an issue using bilinear interpolation for 16 bit data. I have two images, origImage and displayImage. I want to use AffineTransformOp to filter origImage through an AffineTransform into displayImage which is the size of the display area. origImage is of type BufferedImage.TYPE_USHORT_GRAY and has a raster of type sun.awt.image.ShortInterleavedRaster. Here is the code I have right now
displayImage = new BufferedImage(getWidth(), getHeight(), origImage.getType());
try {
op = new AffineTransformOp(atx, AffineTransformOp.TYPE_BILINEAR);
op.filter(origImage, displayImage);
}
catch (Exception e) {
e.printStackTrace();
}
In order to show the error I have created 2 gradient images. One has values in the 15 bit range (max of 32767) and one in the 16 bit range (max of 65535). Below are the two images
15 bit image
16 bit image
These two images were created in identical fashions and should look identical, but notice the line across the middle of the 16 bit image. At first I thought that this was an overflow problem however, it is weird that it's manifesting itself in the center of the gradient instead of at the end where the pixel values are higher. Also, if it was an overflow issue than I would suspect that the 15 bit image would have been affected as well.
Any help on this would be greatly appreciated.
I was just wondering why no one is answering, did I provide enough information? Is more info needed?
Below is the code I use to generate the AffineTransform. All of the referenced variables are calculated based off of user input (mouse movement) and should be correct (it's been tested by a lot of people including myself). Hopefully this can help with the error.
AffineTransform panTranslate = new AffineTransform();
panTranslate.translate(imagePanOffset.x, imagePanOffset.y);
AffineTransform rotateCenterTranslate = new AffineTransform();
rotateCenterTranslate.translate(imageRotateCTR.x, imageRotateCTR.y);
AffineTransform rotateTransform = new AffineTransform();
rotateTransform.rotate(Math.toRadians(rotateValue));
AffineTransform rotateAntiCenterTranslate = new AffineTransform();
rotateAntiCenterTranslate.translate(-imageRotateCTR.x, -imageRotateCTR.y);
AffineTransform translateTransform = new AffineTransform();
translateTransform.translate(imageMagOffset.x, imageMagOffset.y);
AffineTransform flipMatrixTransform = new AffineTransform();
switch (flipState) {
case ENV.FLIP_NORMAL: // NORMAL
break;
case ENV.FLIP_TOP_BOTTOM: // FLIP
flipMatrixTransform.scale(1.0, -1.0);
flipMatrixTransform.translate(0.0, -h);
break;
case ENV.FLIP_LEFT_RIGHT: // MIRROR
flipMatrixTransform.scale(-1.0, 1.0);
flipMatrixTransform.translate(-w, 0.0);
break;
case ENV.FLIP_TOP_BOTTOM_LEFT_RIGHT: // FLIP+MIRROR
flipMatrixTransform.scale(-1.0, -1.0);
flipMatrixTransform.translate(-w, -h);
break;
}
scaleTransform = new AffineTransform();
scaleTransform.scale(magFactor, magFactor);
AffineTransform atx = new AffineTransform();
atx.concatenate(panTranslate);
atx.concatenate(rotateCenterTranslate);
atx.concatenate(rotateTransform);
atx.concatenate(rotateAntiCenterTranslate);
atx.concatenate(translateTransform);
atx.concatenate(flipMatrixTransform);
atx.concatenate(scaleTransform);
I still have no idea what's going on here. I'd really appreciate any help that can be provided. I've also attached an example of the bug happening in a real image that I encounter for more reference.
Here is the bug happening in an X-ray of the hand
Here is a zoomed up version focused on the area between the thumb and first finger.
Note again how the bug doesn't occur on the extremely white areas, but on the values in the middle of the dynamic range, just like in the gradient image.
I've discovered more information. I was adjusting some of the transforms and found that the bug does not occur if I just filter through an identity matrix. It also doesn't occur if I translate by an integer amount. It does occur if I translate by a non integer amount. It also occurs if I zoom by any amount other than 1 (integer or not). Hopefully this helps.
After more experimenting, the bug definitely manifests itself at the boundary pixels between half the max intensity (65535/2 = 32767.5). It also ONLY occurs at this value. I hope this might help diagnosis!!
At the request of AlBlue here is code that is completely independent of my application that can generate the bug. Note that in the original post I included an image gradient generated with the below code however I zoomed in on one of the gradients to better show the effect. You should see the effect four times on the 0.5 translated image and not on either of the other two images. Also note that this bug appears while scaling by any amount other than 1. Just replace AffineTransform.getTranslateInstance() with AffineTransform.getScaleInstance(0.9, 0.9) to see the bug also.
private static class MyJPanel extends JPanel {
BufferedImage displayImage = null;
public MyJPanel(double translateValue) {
super();
BufferedImage bi = new BufferedImage(1024, 1024, BufferedImage.TYPE_USHORT_GRAY);
int dataRange = (int)Math.pow(2, 16);
double step = dataRange/(bi.getRaster().getDataBuffer().getSize()/4.0);
double value = 0;
for (int i=0; i<bi.getRaster().getDataBuffer().getSize(); i++) {
bi.getRaster().getDataBuffer().setElem(i, (int)value);
if (value >= dataRange)
value = 0;
else
value += step;
}
displayImage = new BufferedImage(bi.getWidth(), bi.getHeight(), bi.getType());
AffineTransform tx = AffineTransform.getTranslateInstance(translateValue, translateValue);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
op.filter(bi, displayImage);
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(displayImage, 0, 0, this);
}
}
private static void showDisplayError() {
JDialog dialog1 = new JDialog();
dialog1.setTitle("No Translation");
MyJPanel panel1 = new MyJPanel(0);
dialog1.getContentPane().add(panel1);
dialog1.setSize(1024, 1024);
dialog1.setVisible(true);
JDialog dialog2 = new JDialog();
dialog2.setTitle("Translation of 0.5");
MyJPanel panel2 = new MyJPanel(0.5);
dialog2.getContentPane().add(panel2);
dialog2.setSize(1024, 1024);
dialog2.setVisible(true);
JDialog dialog3 = new JDialog();
dialog3.setTitle("Translation of 1.0");
MyJPanel panel3 = new MyJPanel(1.0);
dialog3.getContentPane().add(panel3);
dialog3.setSize(1024, 1024);
dialog3.setVisible(true);
}
As another update, I just tried this on Fedora 10 and saw the bug is still present.
What version of java (java -version) and OS are you using? It might be a bug in the transform (which has since been fixed) or it might be an error in the rendering to PNG.
Have you tried using a NEAREST_NEIGHBOR filter instead of the BILINEAR one?
You can work around it by applying the transform in a Graphics2D instead of an AffineTransformOp:
if (useG2D) {
Graphics2D g = displayImage.createGraphics();
g.transform(tx);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(bi, null, 0, 0);
} else {
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
op.filter(bi, displayImage);
}
I don't know why this would give different output, but it does.
Note: useG2D could be a constant or it could be set based on the result of tx.getType(). The bug does not occur with TYPE_QUADRANT_ROTATION, TYPE_FLIP or TYPE_IDENTITY transforms.
Did you solve this? It is likely a being caused by not using the AffineTransformOp correctly. How did you create the AffineTransform atx ? If I have that I should be able to replicate to help debug.
You may wish to have a look at this site too. It contains lots of useful information about AffineTransformOp