I am trying to run an AnyLogic model developed a few years ago and I do not have access to the person who coded it. I have very limited knowledge of Java. The model is built based on data being read in from an XML file. The first step is to read the layout data from an XML file and draw the layout. It used to work fine but with AnyLogic version changes, it stopped working. I get the following error:
" (RectangularNode) : The creation of space markup element isn't finished. Please use initialize() function."
The code that gets highlighted as the source of the error is:
((Agent)temp).setLocation(shapeLayoutObj);
What is interesting is that couple RectangularNodes do get drawn before this error occurs. The surrounding code is given below. The above statement identified in the console window as the error source is close to the bottom of the code provided below.
/* Layout drawing */
//Initializing objects
int scale=30;
Layout layout= CMSDDocument.getDataSection().getLayout();
List<LayoutObject> layoutObj =CMSDDocument.getDataSection().getLayoutObject();
double xLoc, yLoc, width, depth;
double xOffset = 50.0;
double yOffset = 100.0;
String layoutName;
width = layout.getBoundary().getWidth().doubleValue()*scale;
depth = layout.getBoundary().getDepth().doubleValue()*scale;
RectangularNode shapeCellArea = new RectangularNode(this, SHAPE_DRAW_2D3D, true, xOffset, yOffset, 0.0, width, depth, 0, null, Color.red, 2.0, LINE_STYLE_SOLID, POSITION_CHOICE_RANDOM, new Attractor(0,0,0));
ShapeText text = new ShapeText(SHAPE_DRAW_2D3D,true,xOffset+width/2,yOffset-20,0.0,0.0,red,"SHOP FLOOR",new Font ("Calibri", Font.BOLD , 15),TextAlignment.ALIGNMENT_CENTER);
presentation.add(shapeCellArea);
presentation.add(text);
LinkedHashMap<String,RectangularNode> floorLayout=new LinkedHashMap<String,RectangularNode>();
boolean found;
int j;
//For every layout description
for(int i= 0; i<layout.getPlacement().size();i++){
//Getting the name and the description
layoutName = layout.getPlacement().get(i).getLayoutElementIdentifier();
xLoc = layout.getPlacement().get(i).getLocation().getX().doubleValue()*scale + xOffset;
yLoc = layout.getPlacement().get(i).getLocation().getY().doubleValue()*scale + yOffset;
found = false;
j = 0;
//Looking for the layout object with tthe same name as the layout description
while (!found && j<layoutObj.size()){
if (layoutName.equals(layoutObj.get(j).getIdentifier())) {
//Getting layou values
width = layoutObj.get(j).getBoundary().getWidth().doubleValue()*scale;
depth = layoutObj.get(j).getBoundary().getDepth().doubleValue()*scale;
RectangularNode shapeLayoutObj=null;
//Configure the shape
if(layoutName.contains("Mc")){
shapeLayoutObj = new RectangularNode(this, SHAPE_DRAW_2D3D, true, xLoc, yLoc, 0.0, width, depth, 0, null, Color.black, 2.0, LINE_STYLE_DASHED, POSITION_CHOICE_BY_ATTRACTORS,new Attractor(width/2,depth/2,0));
}
else{
shapeLayoutObj = new RectangularNode(this, SHAPE_DRAW_2D3D, true, xLoc, yLoc, 0.0, width, depth, 0, null, Color.black, 2.0, LINE_STYLE_DASHED, POSITION_CHOICE_RANDOM);
}
text = new ShapeText(SHAPE_DRAW_2D3D,true,xLoc+width/2,yLoc-15,0.0,0.0,black,layoutName,new Font ("Calibri", Font.PLAIN , 11),TextAlignment.ALIGNMENT_CENTER);
presentation.add(shapeLayoutObj);
presentation.add(text);
//Associate the shape with a machine or a delay
Iterator<ArrayList<Machine>> cell=machineList.iterator();
boolean foundAgent=false;
while(cell.hasNext()&&!foundAgent){
Iterator<Machine> machines=cell.next().iterator();
while(machines.hasNext()&&!foundAgent){
Machine temp=((Machine)machines.next());
if(temp.name.equals(layoutName)){
foundAgent=true;
((Agent)temp).setLocation(shapeLayoutObj);
ShapeButton button = new ShapeButton(Main.this, true, xLoc,yLoc+depth+5,40, 20.0,controlDefault, controlDefault,
true,new Font("Dialog", 0, 11 ),"Go to" ) {
public void action(){
getExperimentHost().setPresentable(temp);
}
};
presentation.add(button);
}
}
}
I understand from past exchanges that AnyLogic switched from Java Swing (in AnyLogic7 when the model was developed) to a Web-based UI and wonder if this error is due to that switch. In AnyLogic help file, RectangularNode function is identified as "deprecated in version 8.4, will be removed in the next release". I am now using AnyLogic 8 Personal Learning Edition 8.5.2 and hence I figure that this function has been removed. Wish the error message said that! Wish also that the help file suggested the new function corresponding to the deprecated function. It is also confusing that "Rectangular Node" continues to show up in the current version as a space markup element on the process modeling library palette. Guess the underlying code has changed for that element.
I looked at AnyLogic help and best I could figure that "ShapeRectangle" may be the new function that I should use to replace "RectangularNode" function but the "ShapeRectangle" function doesn't allow defining attractors. And the "ShapeRectangle" function appears to correspond to Rectangle element in the Presentation Palette rather than to the Rectangular Node in Process Modeling Library.
Kindly point me in the right direction. Should I be replacing all instances of RectangularNode or is the error something else? If I should be replacing the RectangularNode function, what function should I be using instead?
A helpful colleague pointed out that:
"
It looks like only the RectangularNode constructors with ShapeDraw parameters are deprecated. The basic one is not.
RectangularNode's parent class AreaNode has a method to add attractors.
This would lead me to think:
a) you should not replace RectangularNode. ShapeRectangle is about shape but you can't just use a shape as a node.
b) AreaNode, the superclass of RectangularNode , has methods to add attractors so you can use those."
Based on the advice and some trial and error, I used the following statements to replace the deprecated version of RectangularNode. The compiler no longer shows the message about the RectangularNode being deprecated.
// Replacement for above statement added below by SJ on 7/3/20
RectangularNode shapeCellArea = new RectangularNode(this);
shapeCellArea.setPos(xOffset, yOffset, 0.0);
shapeCellArea.setLineColor(Color.red);
shapeCellArea.setLineStyle(LINE_STYLE_SOLID);
shapeCellArea.setLineWidth(2.0);
shapeCellArea.setPositionChoiceMode(POSITION_CHOICE_RANDOM);
shapeCellArea.setSize(width,depth);
shapeCellArea.addAttractor(new Attractor(0,0,0));
// ShapeDrawMode SHAPE_DRAW_2D3D is default mode so don't have to set that.
// end of code added by SJ on 7/3/20
Unfortunately the above changes did not remove the error. Still trying to figure out the error message and will post it as a new question.
---------- The above progress update was posted on July 4, 2020. Additional information below added on July 17, 2020 ------------
With some onlines searches and guided by the answer to another question by #Florian at How can i create Path space markup element in Anylogic via Code, I have addressed the problem by adding all the nodes to a network, adding the network to a level, and then initializing the level. The updated code is below.
Network netwkSJ = new Network(this, "mynetwork");
....
LinkedHashMap<String,RectangularNode> floorLayout=new LinkedHashMap<String,RectangularNode>();
// the loop in the original question here
// added the following statement within the loop
.......
netwkSJ.add(shapeLayoutObj);
floorLayout.put(layoutName, shapeLayoutObj);
// Commented out the statement that was generating the error in the loop
// and moved it within the new loop below
//((Agent)temp).setLocation(shapeLayoutObj); // statement giving error
.......
Level level = new Level(this, "myLevel", SHAPE_DRAW_2D3D, 0);
level.add(netwkSJ);
level.initialize(); // cannot be changed after initialization!
Set set = floorLayout.entrySet();
// iterating through elements of floorLayout to link machines to corresponding layout locations
floorLayout.forEach((Name,node) -> {
//Associate the node with a machine
Iterator<ArrayList<Machine>> cell=machineList.iterator();
boolean foundAgent=false;
while(cell.hasNext()&&!foundAgent){
Iterator<Machine> machines=cell.next().iterator();
while(machines.hasNext()&&!foundAgent){
Machine temp=((Machine)machines.next());
if(temp.name.equals(Name)){
foundAgent=true;
((Agent)temp).setLocation(node);
// System.out.println(Name + " -> " );
}
};
};
});
Related
I have an XSSFSheet with images at the end of my used rows. When adding a new row, I would like to shift all images one row down. I have found this similar question about moving charts, and have tried to use the part of the answer that does the actual moving of the charts, because It looked like it would work for images as well.
java.util.List<CTTwoCellAnchor> drawingAnchors = ((XSSFDrawing)sheet.getDrawingPatriarch()).getCTDrawing().getTwoCellAnchorList();
for (CTTwoCellAnchor drawingAnchor : drawingAnchors) {
int fromRow = drawingAnchor.getFrom().getRow();
int toRow = drawingAnchor.getTo().getRow();
if (fromRow >= startRow) {
drawingAnchor.getFrom().setRow(fromRow + n);
drawingAnchor.getTo().setRow(toRow + n);
}
}
but this did not work but throws a NoClassDefFoundError instead.
(Edit: I now found out that this error can be solved by providing the full jar of all of the schemas ooxml-schemas as mentioned in FAQ-N10025. thanks #Axel Richter)
After trying out several different approaches, I found a way to do it. Since it took me so long, and there is no info about this anywhere yet, I decided to post my findings here on SO.
Please find my solution in my own answer. Cheers
The following code gets the Drawing Patriarch of the sheet, iterates over all it's shapes, and if the shape is of type XSSFPicture it modifies the rowindexes through its XSSFClientAnchor.
int moveRowsBy = 1; // 1 will move the images 1 row down. moveRowsBy can be negative to move up
XSSFDrawing drawing = sheet.getDrawingPatriarch();
for (XSSFShape shape : drawing.getShapes()) {
if (shape instanceof XSSFPicture){
XSSFClientAnchor anchor = ((XSSFPicture)shape).getClientAnchor();
anchor.setRow1(anchor.getRow1() +moveRowsBy);
anchor.setRow2(anchor.getRow2() +moveRowsBy);
// if needed you could change column too, using one of these:
// anchor.setCol1(newColumnInt)
// anchor.setCol1(anchor.getCol1() + moveColsBy)
}
}
I am using OpenGL ES 3.2 and the NVIDIA driver 361.00 on a Pixel C tablet with Tegra X1 GPU. I would like to use a compute shader to write data to a colour map and then later I will use some graphics shaders to display the image.
I already have this concept working using desktop GL and now I want to port to mobile. I am implementing the GL in Java rather than in native code. I extend GLSurfaceView and the GLSurfaceView.Renderer and then during the OnSurfaceCreated callback I initialise the shader programs and textures etc.
The compute shader compiles just fine without any errors:
#version 310 es
layout(binding = 0, rgba32f) uniform highp image2D colourMap;
layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
void main()
{
imageStore(colourMap, ivec2(gl_GlobalInvocationID.xy), vec4(1.0f, 0.0f, 0.0f, 1.0f));
}
And I initialise a texture
// Generate a 2D texture
GLES31.glGenTextures(1, colourMap, 0);
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, colourMap[0]);
// Set interpolation to nearest
GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR);
GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_LINEAR);
// Create some dummy texture to begin with so we can see if it changes
float texData[] = new float[texWidth * texHeight * 4];
for (int j = 0; j < texHeight; j++)
{
for (int i = 0; i < texWidth; i++)
{
// Set a few pixels in here...
}
}
Buffer texDataBuffer = FloatBuffer.wrap(texData);
GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA32F, texWidth, texHeight, 0, GLES31.GL_RGBA, GLES31.GL_FLOAT, texDataBuffer);
After this I set the image unit in the shader here: EDIT: I don't do this now but just assume it will be assigned automatically when the shader program is created as per solidpixel's answer.
GLES31.glUseProgram(idComputeShaderProgram);
int loc = GLES31.glGetUniformLocation(idComputeShaderProgram, "colourMap");
if (loc == -1) Log.e("Error", "Cannot locate variable");
GLES31.glUniform1i(loc, 0);
After every call to GL I check for errors using GLES31.glGetError() -- left out here for clarity.
EDIT: When I dispatch compute I bind the image texture but first query the unit assignment:
GLES31.glUseProgram(idComputeShaderProgram);
int[] unit = new int[1];
GLES31.glGetUniformiv(idComputeShaderProgram, GLES31.glGetUniformLocation(idComputeShaderProgram, "colourMap"), unit, 0);
GLES31.glBindImageTexture(unit[0], velocityMap[0], 0, false, 0, GLES31.GL_WRITE_ONLY, GLES31.GL_RGBA32F);
This final line is the one which errors now. The error code translates to GL_INVALID_OPERATION. The shader compiles correctly and the program object is valid and active. The location of the variable is also valid. I have even used glGetActiveUniform() to get the type of the variable and it returns a type of 36941 which translates to GL_IMAGE_2D which I believe is an integer.
I still think I'm misunderstanding something here but not sure what.
You can't assign your own unit identities for images. See OpenGL ES 3.2 specification section 7.6.
An INVALID_OPERATION error is generated if any of the following
conditions occur:
an image uniform is loaded with any of the Uniform* commands.
You need to query the automatic unit assignment using glGetUniformiv(prog, loc, &unit) to get the unit name.
I want to reproject an geospatial image using GDAL compiled for Android. I am currently using the swig bindings but am considering going jni/ndk.
I have successfully warped an image with the AutoCreateWarpedVRT function, but I would like to use more options (e.g. cropping the output). Currently the below is my attempt at warping using the Warp. It produces an output raster that is not warped at all, and also is not applying the -te options.
The documentation for the GDAL swig bindings is very sparse (link) and I suspect that I did not get the WarpOptions right.
Any suggestions on how to make the WarpOptions(Vector) arguments work (or any of the ???Options(Vector) for that sake) is appreciated.
Dataset src = gdal.Open("input_raster.jpg");
src.SetProjection(src_wkt);
// Set reference points
double west = 451000;
double east = 501005;
double south = 6214995;
double north = 6257000;
int width = src.getRasterXSize();
int height = src.getRasterYSize();
GCP[] gcps = { new GCP(0, 0, west, north),
new GCP(0, height, west, south),
new GCP(width, 0, east, north),
new GCP(width, height, east, south)};
src.SetGCPs(gcps, dst_wkt);
// Try to warp
Dataset[] src_array = {src};
WarpOptions warpOptions = new WarpOptions(
new Vector(Arrays.asList("s_srs EPSG:32632", "t_srs EPSG:3857", "te 1000 820"))
);
Dataset warp = gdal.Warp("warp.vrt", src_array, warpOptions);
Dataset warp_png = driverPNG.CreateCopy("warp_raster.png", warp);
//Produces a raster output without errors, but does not apply the warp.
src.delete();
warp.delete();
warp_png.delete();
According to this discussion the syntax should be:
Vector<String> options = new Vector<>();
options.add("-s_srs");
options.add("EPSG:32632");
options.add("-t_srs");
options.add("EPSG:3857");
Seems great, but throws a runtime error WarpOptions.java:17
if (cPtr == 0)
throw new RuntimeException();
So, apart from the error I think the solution is correct. The error may be platform specific.
Resources and examples for this Popup widget are vague.
Suppose I have a random Node somewhere on the stage. How do I open a Popup exactly under it (e.g. like a dropdown menu, but with other nodes inside it).
I'm trying to avoid boilerplate code (i.e. fine-tuning the position myself).
Update 1:
Either Point2D point = node.localToScene(0.0, 0.0); does not work as I imagine it should, or I'm using it wrong.
Update 2:
See here a simple example, but lacking the functionality I'm needing
Let's say you have the node node
you can get its position by
Point2D point = node.localToScene(0.0, 0.0);
// now get point.getX() and point.getY() here
Considering the example that you have given (in Update 2):
I removed this bit:
popup.setX(300);
popup.setY(200);
and modified this code:
show.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
popup.show(primaryStage);
Point2D point = show.localToScene(0.0, 0.0);
popup.setX(primaryStage.getX() + point.getX());
popup.setY(primaryStage.getY() + point.getY() + 40);
// this 40 could be show.getPrefHeight() if height of button is set
}
});
Since Popup is a separate window, you need to set its position by adding the offset of the Stage.
I am using vaadin and for some visual data analysis I've added the addon InvientCharts for vaadin (https://vaadin.com/directory#addon/invient-charts).
Is it possible to dynamically change the x- and y-axis Caption of the scattertchart (so after the chart has been created)?
I'm currently having a scatterchart and a button. When the button is clicked, all existing points (Series) shall be removed, the x- and y-axis caption shall change and the new points shall be added on the chart.
That's the code snippet with which I'm trying it currently:
public void changePoints(String xAxisTitle, String yAxisTitle, List<List<double[]>> xAndYCoordinates) {
// remove all points from the scatterchart - THIS IS WORKING
Object[] allSeries = chart.getAllSeries().toArray();
for(int j = 0; j < allSeries.length; j++){
Series serie = (Series) allSeries[j];
chart.removeSeries(serie);
}
// update the x- and y-axis - THIS IS NOT WORKING AND WHAT I'M TALKING ABOUT
chartConfig.getXAxes().clear();
chartConfig.getYAxes().clear();
NumberXAxis xAxis = new NumberXAxis();
xAxis.setTitle(new AxisTitle(xAxisTitle));
xAxis.setStartOnTick(true);
xAxis.setEndOnTick(true);
xAxis.setShowLastLabel(true);
LinkedHashSet<XAxis> xAxesSet = new LinkedHashSet<InvientChartsConfig.XAxis>();
xAxesSet.add(xAxis);
chartConfig.setXAxes(xAxesSet);
NumberYAxis yAxis = new NumberYAxis();
yAxis.setTitle(new AxisTitle(yAxisTitle));
LinkedHashSet<YAxis> yAxesSet = new LinkedHashSet<InvientChartsConfig.YAxis>();
yAxesSet.add(yAxis);
chartConfig.setYAxes(yAxesSet);
// add the new points - THIS IS WORKING AGAIN
for (int i = 0; i < versionDates.size(); i++) {
String versionDate = versionDates.get(i);
List<double[]> versionValues = xAndYCoordinates.get(i);
ScatterConfig versionScatterConfig = new ScatterConfig();
XYSeries series = new XYSeries("Version " + (i + 1) + " - "
+ versionDate, versionScatterConfig);
series.setSeriesPoints(getPoints(series, versionValues));
chart.addSeries(series);
}
}
As you can see, the removing and adding of points works perfectly fine, which I assume is because I'm working directly on the chart here, while I'm working on the chartConfig when I try to change the axes caption.
Could you please tell or show me how I can change the caption of the x- and y-Axis in an already existing chart (As described above)?
Thanks a lot
After a lot of research I've come to the conclusion that there seems to be currently no way of changing the x- and yAxis caption dnymically, which works.
I found out that if you refresh the page, e.g. by pressing F5, the axes caption gets changed. I've tried implementing a refresher, but somehow the behaviour still didn't change.
So it looks like a bug (or software failure) for me.
My workaround which is doing the same is just removing the whole chart and then adding a completely new one with the new Axis-caption. This works perfectly fast and fine, but is a dirty solution in my eyes, since you have to add more lines of codes than necessary, as well as the logic is now basically more complicated then it should be.