I have the following code:
GridLayout grid = new GridLayout(3, 3);
grid.addComponent(btnRemove, 0, 0);
grid.addComponent(lblIstMenge, 1, 0);
grid.addComponent(btnAdd, 2, 0);
int i = 0;
if (vList != null && vList.size() > 0)
{
for (VTr component : vList)
{
String transactionTypeName = component.getTransactionTypeName();
transaktionTable.addItem(new Object[]{++transaktionTableCounter + "",
transactionTypeName,
"123123123123123", grid, "Bemerkung^^^"},
transaktionTableCounter);
// System.out.println("Grid: " + grids.get(i));
}
}
Which gives me something like this:
So the grid is added only in the last column. I have tried creating different grids for each column in a list but this did not work for me.
If you have any ideas or recommendations it would be nice.
When I move the instantiation of the buttons and grids inside the for loop it is working as expected.
int i = 0;
if (vList != null && vList.size() > 0)
{
for (VTr component : vList)
{
btnAdd = new Button();
btnAdd.setIcon(new ThemeResource("images/btnIncrease.png"));
btnRemove = new Button();
btnRemove.setIcon(new ThemeResource("images/btnDescrease.png"));
GridLayout grid = new GridLayout(3, 3);
grid.addComponent(btnRemove, 0, 0);
grid.addComponent(lblIstMenge, 1, 0);
grid.addComponent(btnAdd, 2, 0);
String transactionTypeName = component.getTransactionTypeName();
transaktionTable.addItem(new Object[]{++transaktionTableCounter + "", transactionTypeName,
"123123123123123", grid, "Bemerkung^^^"}, transaktionTableCounter);
}
}
Related
I have a TextView that needs to be highlighted in multiple positions.
I've done this before with EditText and it worked fine.
The only difference is that EditText implements Spannable whereas TextView doesn't.
TextView seems to remain span only from the last setSpan() method call.
Code
TextView tvMainActivityTitle = findViewById(R.id.tvMainActivityTitle);
SpannableString spanStr = new SpannableString(tvMainActivityTitle.getText());
ForegroundColorSpan color = new ForegroundColorSpan(Color.rgb(192,0,0));
spanStr.setSpan(color, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanStr.setSpan(color, 2, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanStr.setSpan(color, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // <- this one wins
tvMainActivityTitle.setText(spanStr);
So it paints only the first character in the TextView.
I assume that TextView struggles with this type of task.
How do I fix this?
You just need multiple instances of ForegroundColorSpan for each set method & it will work.
For your example:
TextView tvMainActivityTitle = findViewById(R.id.tvMainActivityTitle);
SpannableString spanStr = new SpannableString(tvMainActivityTitle.getText());
ForegroundColorSpan color1 = new ForegroundColorSpan(Color.rgb(192, 0, 0));
ForegroundColorSpan color2 = new ForegroundColorSpan(Color.rgb(192, 0, 0));
ForegroundColorSpan color3 = new ForegroundColorSpan(Color.rgb(192, 0, 0));
spanStr.setSpan(color1, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanStr.setSpan(color2, 2, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanStr.setSpan(color3, 5, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // <- this one wins
tvMainActivityTitle.setText(spanStr);
Also for further read: https://www.geeksforgeeks.org/text-styling-with-spans-in-android/
Refer #Mayur Gajra's answer for the solution.
Adding the reason why this happens for better understanding.
So, we can see that each span can only be used to set one span.
Why is that so?
On digging up the SpannableString setSpan(), I can see this code,
for (int i = 0; i < count; i++) {
if (spans[i] == what) {
int ostart = data[i * COLUMNS + START];
int oend = data[i * COLUMNS + END];
data[i * COLUMNS + START] = start;
data[i * COLUMNS + END] = end;
data[i * COLUMNS + FLAGS] = flags;
sendSpanChanged(what, ostart, oend, nstart, nend);
return;
}
}
what is the span argument passed to the setSpan method. what is an object.
Hence if (spans[i] == what) checks if there is already a span set with the same instance. If so, the span is replaced with the new span.
I am currently trying to iterate over every pixel of a black and white image in OpenCV 4.1.2 in Java and to store e 3x3 Matrix for every pixel, which should have a 1, if the pixel currently worked with has e neighbouring pixel there, and an 0 if there is no neighbour at this position. So the value in the center of the Mat should always be 1. Currently im working with that nested for-loops, that should iterate through the Mat.
Mat bwDrawing = new Mat(drawing.size(), CvType.CV_8UC3);
Imgproc.cvtColor(drawing, bwDrawing, Imgproc.COLOR_RGB2GRAY);
List<MatOfInt> freemanChains = new ArrayList<>();
for (double y = 2; y-2 < bwDrawing.size().height; y++) {
for (double x = 2; x-2 < bwDrawing.size().width; x++) {
MatOfInt freemanMat = new MatOfInt();
if (bwDrawing.get((int)y-1, (int)x-1)[0] != 0) {
freemanMat.put(0, 0, 1);
} else {
freemanMat.put(0,0, 0);
}
if (bwDrawing.get((int)y-1, (int)x)[0] != 0) {
freemanMat.put(0, 1, 1);
} else {
freemanMat.put(0,1, 0);
}
if (bwDrawing.get((int)y-1, (int)x+1)[0] == 0) { //right here is the NullPointer Exception
freemanMat.put(0, 2, 1);
} else {
freemanMat.put(0,2, 0);
}
if (bwDrawing.get((int)y, (int)x-1)[0] != 0) {
freemanMat.put(1, 0, 1);
} else {
freemanMat.put(1,0, 0);
}
if (bwDrawing.get((int)y, (int)x)[0] != 0) {
freemanMat.put(1, 1, 1);
} else {
freemanMat.put(1,1, 0);
}
if (bwDrawing.get((int)y, (int)x+1)[0] != 0) {
freemanMat.put(1, 2, 1);
} else {
freemanMat.put(1,2, 0);
}
if (bwDrawing.get((int)y+1, (int)x-1)[0] != 0) {
freemanMat.put(2, 0, 1);
} else {
freemanMat.put(2,0, 0);
}
if (bwDrawing.get((int)y+1, (int)x)[0] != 0) {
freemanMat.put(2, 1, 1);
} else {
freemanMat.put(2,1, 0);
}
if (bwDrawing.get((int)y+1, (int)x+1)[0] != 0) {
freemanMat.put(2, 2, 1);
} else {
freemanMat.put(2,2, 0);
}
freemanChains.add(freemanMat);
// System.out.println(freemanMat.get(2, 2)[0]);
}
}
As marked by the comment in the code, im getting an NullPointer Exception the first time im checking for a pixel at x+1. And i do not understand why.
My overall goal is tho calculate a Freeman Chain Code of some contours, and i hope to achieve it with that somehow. Are there any other options in OpenCV to get the Freeman Chain Code since they removed it from the findContours() function?
Any help to both problems is much appreciated. Thank you.
I'm filling a container with a lot of small boxes and the problem is that you can see trough them from some angles. I've already enabled the depth buffer, but that doesn't work.
The code that handles this part is split into 3. setupUIPreElements sets everything up, setupUIElements adds the boxes and setupUIPostElements adds the container and some camera stuff.
public static void setupUIPreElements(Stage stage){
//Setup grids, groups, scenes, camera and such so that the scene is made from scratch
topGrid = new GridPane();
twoDGroup = new Group();
threeDGroup = new SmartGroup();
root = new HBox();
mainScene = new Scene(root, SCREEN_WIDTH, SCREEN_HEIGHT, true, SceneAntialiasing.BALANCED);
twoD = new SubScene(twoDGroup, SCREEN_WIDTH*.2, SCREEN_HEIGHT);
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT);
anchorAngleX = 0;
anchorAngleY = 0;
angleX = new SimpleDoubleProperty(0);
angleY = new SimpleDoubleProperty(0);
camera = new PerspectiveCamera();
pins = new ProgressIndicator[1];
pin = pins[0] = new ProgressIndicator();
parcels = new ArrayList<UIParcel>();
//add subscenes to scene
root.getChildren().addAll(twoD, threeD);
root.setSpacing(10);
root.setPadding(new Insets(20, 20, 20, 20));
/*START Setup top menu*/
//Setup grid
topGrid.setHgap(10);
topGrid.setVgap(10);
//Setup items
//Add scoring label
scoringLabel = new Label("Score: " + Wrapper.score);
startButton = new Button("Start");
modeSelection = new ChoiceBox(FXCollections.observableArrayList(
"Parcels", "Pentominoes"
));
modeSelection.setValue("");
//Parcel selection UI
ParcelAAmountLabel = new Label("Amount of parcel A: ");
ParcelBAmountLabel = new Label("Amount of parcel B: ");
ParcelCAmountLabel = new Label("Amount of parcel C: ");
ParcelAAmountTextField = new TextField();
ParcelBAmountTextField = new TextField();
ParcelCAmountTextField = new TextField();
ParcelAValueLabel = new Label("Value of parcel A: ");
ParcelBValueLabel = new Label("Value of parcel B: ");
ParcelCValueLabel = new Label("Value of parcel C: ");
ParcelAValueTextField = new TextField();
ParcelBValueTextField = new TextField();
ParcelCValueTextField = new TextField();
//Pentominoe selection UI
LPentominoAmountLabel = new Label("Amount of L pentominoes: ");
PPentominoAmountLabel = new Label("Amount of P pentominoes: ");
TPentominoAmountLabel = new Label("Amount of T pentominoes: ");
LPentominoAmountTextField = new TextField();
PPentominoAmountTextField = new TextField();
TPentominoAmountTextField = new TextField();
LPentominoValueLabel = new Label("Value of L pentominoes: ");
PPentominoValueLabel = new Label("Value of P pentominoes: ");
TPentominoValueLabel = new Label("Value of T pentominoes: ");
LPentominoValueTextField = new TextField();
PPentominoValueTextField = new TextField();
TPentominoValueTextField = new TextField();
//-1 will make it display an animated disk, set to 1 to show that it's done
//pin is the progress indicator
pin.setProgress(-1);
topGrid.add(scoringLabel, 0, 0);
topGrid.add(modeSelection, 0, 1);
topGrid.add(startButton, 0, 8);
twoDGroup.getChildren().add(topGrid);
/*END*/
//Set materials
container_material.setDiffuseColor(CONTAINER_COLOR);
edge_material.setDiffuseColor(EDGE_COLOR);
}
public static void setupUIElements(Stage stage, int[][][] resultBoxesArray){
//TODO check if I can assume the IDs to be either 1, 2 or 3 if filled in or 0 if not
int colorStart = 0;
int colorEnd = 0;
//give every filled in field a box representation and keep color in mind
//create all the boxes
for(int x=0; x<resultBoxesArray.length; x++){
for(int y=0; y<resultBoxesArray[x].length; y++){
for(int z=0; z<resultBoxesArray[x][y].length; z++){
int currentValue = resultBoxesArray[x][y][z];
//if this field is filled
if(currentValue!=0){
//update color range
if(currentValue==1){
colorStart = 0;
colorEnd = 70;
} else if (currentValue==2){
colorStart = 85;
colorEnd = 155;
} else {
colorStart = 170;
colorEnd = 255;
}
//50 is used because that is the size that is given for each cell in the array
UIParcel cellBox = new UIParcel(x*50, y*50, z*50, 50, 50, 50, colorStart, colorEnd);
parcels.add(cellBox);
}
}
}
}
//show them
threeDGroup.getChildren().addAll(parcels);
}
public static void setupUIPostElements(Stage stage){
//Create container (note: Has to be created after adding all the other objects in order to use transparency (I know, javaFX can be crappy))
Box container = new Box(Wrapper.CONTAINER_WIDTH, Wrapper.CONTAINER_HEIGHT, Wrapper.CONTAINER_DEPTH);
container.setTranslateX(Wrapper.CONTAINER_WIDTH/2);
container.setTranslateY(Wrapper.CONTAINER_HEIGHT/2);
container.setTranslateZ(Wrapper.CONTAINER_DEPTH/2);
container.setMaterial(container_material);
threeDGroup.getChildren().add(container);
//Setup camera (so that you can have the container at the origin and can still see it well
//The +threeDOffsetLeft comes from the compensation for the 2D subscene on the left
camera.setTranslateX(-SCREEN_WIDTH/2+Wrapper.CONTAINER_WIDTH/2+threeDOffsetLeft);
camera.setTranslateY(-SCREEN_HEIGHT/2+Wrapper.CONTAINER_HEIGHT/2);
camera.setTranslateZ(-Wrapper.CONTAINER_DEPTH/0.5);
//Setup mouse rotation
initMouseControl(threeDGroup, mainScene, stage);
//Set eventListener for mode selection
modeSelection.getSelectionModel().selectedItemProperty().addListener((v, oldValue, newValue) -> {
//check what mode was selected and show the corresponding options
if(newValue.equals("Parcels")){
//remove other option
if(oldValue.equals("Pentominoes")){
topGrid.getChildren().removeAll(LPentominoAmountLabel, PPentominoAmountLabel, TPentominoAmountLabel, LPentominoAmountTextField, PPentominoAmountTextField, TPentominoAmountTextField, LPentominoValueLabel, PPentominoValueLabel, TPentominoValueLabel, LPentominoValueTextField, PPentominoValueTextField, TPentominoValueTextField);
}
//add labels
topGrid.add(ParcelAAmountLabel, 0, 2);
topGrid.add(ParcelBAmountLabel, 0, 4);
topGrid.add(ParcelCAmountLabel, 0, 6);
topGrid.add(ParcelAValueLabel, 0, 3);
topGrid.add(ParcelBValueLabel, 0, 5);
topGrid.add(ParcelCValueLabel, 0, 7);
//add text fields
topGrid.add(ParcelAAmountTextField, 1, 2);
topGrid.add(ParcelBAmountTextField, 1, 4);
topGrid.add(ParcelCAmountTextField, 1, 6);
topGrid.add(ParcelAValueTextField, 1, 3);
topGrid.add(ParcelBValueTextField, 1, 5);
topGrid.add(ParcelCValueTextField, 1, 7);
} else if (newValue.equals("Pentominoes")){
//remove other option
if(oldValue.equals("Parcels")){
topGrid.getChildren().removeAll(ParcelAAmountLabel, ParcelBAmountLabel, ParcelCAmountLabel, ParcelAAmountTextField, ParcelBAmountTextField, ParcelCAmountTextField, ParcelAValueLabel, ParcelBValueLabel, ParcelCValueLabel, ParcelAValueTextField, ParcelBValueTextField, ParcelCValueTextField);
}
//add labels
topGrid.add(LPentominoAmountLabel, 0, 2);
topGrid.add(PPentominoAmountLabel, 0, 4);
topGrid.add(TPentominoAmountLabel, 0, 6);
topGrid.add(LPentominoValueLabel, 0, 3);
topGrid.add(PPentominoValueLabel, 0, 5);
topGrid.add(TPentominoValueLabel, 0, 7);
//add text fields
topGrid.add(LPentominoAmountTextField, 1, 2);
topGrid.add(PPentominoAmountTextField, 1, 4);
topGrid.add(TPentominoAmountTextField, 1, 6);
topGrid.add(LPentominoValueTextField, 1, 3);
topGrid.add(PPentominoValueTextField, 1, 5);
topGrid.add(TPentominoValueTextField, 1, 7);
}
});
//Set evenListener for start button
startButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event-> {
//Show loading circle (that was created at the start)
topGrid.add(pin, 0, 9);
//TODO use values from the textFields as input
//TODO start calculations
//TODO remove after testing
test.giveInput();
});
threeD.setCamera(camera);
stage.setTitle("Filling 3D objects");
threeD.setFill(BACKGROUND_COLOR);
stage.setScene(mainScene);
stage.show();
}
From the angle that works as desired is looks like this:
From the angle that doesn't work properly it looks like this:
Note that the boxes are added as UIParcel, this is just a class that extends the regular Box with some extra info, it doesn't effect any 3D stuff.
The solution was to also enable depth buffering for the SubScene that contained the 3D elements, it doesn't just follow the settings from the mainScene.
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT);
becomes
threeD = new SubScene(threeDGroup, SCREEN_WIDTH*.8, SCREEN_HEIGHT, true, SceneAntialiasing.BALANCED);
Setting the SceneAntialiasing is also required by the SubScene constructor.
I am working on a licence plate recognition software using OpenCV, Tesseract and Java but experiencing issues, I cant seem to segment my text correctly, its not always that I get all characters to be detected and bounded with a bounding box these are some of my outputs with my code...and also when I detect the characters I never know which character is in which box so when I pass them through tesseract they get jumbled, how do I format my string?
This one fails despite the clearly visible characters:
Here Z and 6 fail to be detected even when 6 is clearly visible:
Below is my code:
originalFrame = image.clone();
roiColor = image.clone();
Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2GRAY, 0);
originalFrameGrayScale = image.clone();
Mat morph = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(9, 9));
Imgproc.morphologyEx(image, image, Imgproc.MORPH_TOPHAT, morph);
Imgproc.Sobel(image, image, -1, 2, 0);
Imgproc.GaussianBlur(image, image, new Size(5,5), 3,3);
Imgproc.morphologyEx(image, image, Imgproc.MORPH_CLOSE, morph);
Imgproc.threshold(image, image, 200, 255, Imgproc.THRESH_OTSU);
Vector<Rect> rectangles = detectionContour(image);
Mat roi = originalFrameGrayScale.clone();
if(!rectangles.isEmpty()){
roi = originalFrameGrayScale.submat(rectangles.get(0));
roiBlack = roi.clone();
roiColor = roiColor.submat(rectangles.get(0));
Imgproc.rectangle(originalFrame, rectangles.get(0).br(), rectangles.get(0).tl(), new Scalar(0,0,255), 2);
}
Imgproc.medianBlur(roi, roi, 3);
Imgproc.adaptiveThreshold(roi, roi, 225, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 15, 3);
roiBinarize = roi.clone();
Mat erode = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 1));
Mat dilate = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(1, 1));
Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_OPEN, dilate);
Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_OPEN, erode);
Imgproc.Canny(roi, roi, 150, 150 * 3, 3, true);
Vector<Rect> letters = detectionPlateCharacterContour(roi);
doTesseractOCR(letters, roiBinarize);
private static void doTesseractOCR(Vector<Rect> letters, Mat plate){
Tesseract instance = new Tesseract(); //
instance.setLanguage(LANGUAGE);
String resultPlate = "";
for(int i= 0; i < letters.size(); i++){
BufferedImage letter = OpenCvUtils.Mat2bufferedImage(plate.submat(letters.get(i)));
try {
String result = instance.doOCR(letter);
resultPlate += result + " position "+i;
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
System.out.println("Tesseract output: "+resultPlate);
}
}
private static Vector<Rect> detectionPlateCharacterContour(Mat roi) {
Mat contHierarchy = new Mat();
Mat imageMat = roi.clone();
Rect rect = null;
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(imageMat, contours, contHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);
Vector<Rect> rect_array = new Vector<>();
for (int i = 0; i < contours.size(); i++) {
rect = Imgproc.boundingRect(contours.get(i));
double ratio = 0;
if(rect.height > rect.width){
ratio = rect.height/rect.width;
}else{
ratio = rect.width/rect.height;
}
Logger.printMessage("Ratio of letter: "+ratio);
double contourarea = Imgproc.contourArea(contours.get(i));
if (contourarea >= 100 && contourarea <= 1000 && ( ratio >= 1 && ratio <= 2)) {
Imgproc.rectangle(roiColor, rect.br(), rect.tl(), new Scalar(255,0,0));
rect_array.add(rect);
}
}
contHierarchy.release();
return rect_array;
}
I am using following code to position the total label on the bar chart's bar. The position is supposedly on the top of the each rendered bar. But some reason the label rendering is messing up the entire chart!
UPDATE Positioning Total Labels issue The totals for each bar should be on the top-center of the each bar! instead it positioned random somewhere near top and not aligned to bars.
Following lines are trouble having rendering chart lable:
ItemLabelAnchor labelAnchor = "O".equals(direction) ? ItemLabelAnchor.OUTSIDE12 : ItemLabelAnchor.INSIDE8;
TextAnchor textAnchor = "O".equals(direction) ? TextAnchor.TOP_CENTER : TextAnchor.CENTER;
TextAnchor rotationAnchor = "O".equals(direction) ? TextAnchor.TOP_CENTER : TextAnchor.BOTTOM_CENTER;
renderer.setSeriesPositiveItemLabelPosition(0,
new ItemLabelPosition(labelAnchor, textAnchor, rotationAnchor, ((angle * Math.PI) / 180)));
I am using jdk 8 with jFreeChart-1.0.19. Following complete code listing:
CategoryPlot plot = chart.getCategoryPlot();
if (plot != null) {
if (log.isDebugEnabled()) {
log.debug("Total Renderers : " + plot.getRendererCount());
}
try {
JRPropertiesMap propMap = jasperChart.getPropertiesMap();
if (propMap.containsProperty(APPLY_LABEL_ROTATION)) {
DecimalFormat dfKey = new DecimalFormat("###,###");
/* {0} - label would be equal to Series expression,
* {1} - label would be equal to Category expression,
* {2} - label would be equal to Value expression
*/
StandardCategoryItemLabelGenerator labelGenerator = new StandardCategoryItemLabelGenerator("{2}", dfKey);
LegendItemCollection lic = new LegendItemCollection();
List<LegendItem> legendList = new ArrayList<LegendItem>();
LegendItem totalOpenLegend = null;
for (int i = 0; i <= (plot.getRendererCount() - 1); i++) {
String prop = propMap.getProperty("Chart_" + (i + 1));
Double angle = null == prop ? 0D : Double.valueOf(prop.substring(0, prop.length() - 1));
String direction = null == prop ? "O" : "" + prop.charAt(prop.length() - 1);
if (log.isDebugEnabled()) {
log.debug("Property value for renerer : " + i + " Chart_" + (i + 1) + " angle : " + angle + ", Direction : " + direction);
}
CategoryItemRenderer renderer = plot.getRenderer(i);
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelGenerator(labelGenerator);
if (i == 0) {
Shape shape = ShapeUtilities.createLineRegion(new Line2D.Double(-6, 0, 6, 0), 1);
((LineAndShapeRenderer) renderer).setSeriesShape(0, shape);
((LineAndShapeRenderer) renderer).setBaseItemLabelsVisible(false);
}
if (i == 1) {
//shape = ShapeUtilities.createLineRegion(new Line2D.Double(0, 0, 1, 1), 2);
((LineAndShapeRenderer) renderer).setBaseShapesFilled(false);
((LineAndShapeRenderer) renderer).setBaseItemLabelPaint(Color.RED);
}
if (i == 2) {
((LineAndShapeRenderer) renderer).setBaseItemLabelsVisible(false);
}
if (i == 3) {
((LineAndShapeRenderer) renderer).setBaseItemLabelPaint(new Color(139, 90, 43));
}
LegendItem item = renderer.getLegendItem(i, 0);
if ((i >= 0) && (i < 4)) {
legendList.add(item);
} else {
totalOpenLegend = item;
BarRenderer barRenderer = (BarRenderer) renderer;
barRenderer.setMaximumBarWidth(0.3);
barRenderer.setItemMargin(0.1);
}
ItemLabelAnchor labelAnchor = "O".equals(direction) ? ItemLabelAnchor.OUTSIDE12 : ItemLabelAnchor.INSIDE8;
TextAnchor textAnchor = "O".equals(direction) ? TextAnchor.TOP_CENTER : TextAnchor.CENTER;
TextAnchor rotationAnchor = "O".equals(direction) ? TextAnchor.TOP_CENTER : TextAnchor.BOTTOM_CENTER;
renderer.setSeriesPositiveItemLabelPosition(0,
new ItemLabelPosition(labelAnchor, textAnchor, rotationAnchor, ((angle * Math.PI) / 180)));
//--
plot.setRenderer(i, renderer);
}
lic.add(totalOpenLegend);
for (LegendItem li : legendList) {
lic.add(li);
}
System.out.println("Setting Legend Items");
plot.setFixedLegendItems(lic);
plot.getDomainAxis().setLowerMargin(0);