We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi,
I'm getting a ConcurrentModificationException and regardless all my efforts to solve the problem I fail, let me explain what I'm doing:
1- Particles are created when the user clicks or drag the mouse
void addNumberAt(float _mx, float _my) {
color dye = gui.getColorPickerValue();
NumberParticle np = new NumberParticle(numbers.size(), dye, _mx, _my);
if (isCanvasNameSet) {
np.belongsToTitle = true;
}
numbers.add(np);
}
This NumberParticles consist of 2 VerletParticle2D and 1 VerletSpring2D
NumberParticle(int _id, color _dye, float _mx, float _my) {
anchor = new VerletParticle2D(new Vec2D(_mx, _my));
world.addParticle(anchor);
world.addBehavior(new AttractionBehavior2D(anchor, repulsiveForceRadius, -repulsiveForce, repulsiveForceJitter));
anchor.lock();
label = new VerletParticle2D(new Vec2D(_mx, _my).addSelf(Vec2D.randomVector().scale(5)));
world.addParticle(label);
world.addBehavior(new AttractionBehavior2D(label, repulsiveForceRadius, -repulsiveForce, repulsiveForceJitter));
spring = new VerletSpring2D(anchor, label, numberSpringAnchorLength, numberSpringAnchorStrength);
world.addSpring(spring);
}
public void kill() {
// anchor.removeAllBehaviors();
// label.removeAllBehaviors();
world.removeSpringElements(spring);
// world.removeSpring(spring);
// world.removeParticle(anchor);
// world.removeParticle(label);
}
2- NumberParticles can also be added when the user adds a name so a bunch of NumberParticles are added at once using the same addNumberAt() method
3- There is a button to remove the last NumberParticle like a Undo button, it flags the item os it can be remove from the list on the next draw loop
void removeNumber() {
ListIterator<NumberParticle> it = numbers.listIterator(numbers.size());
if (it.hasPrevious()) {
NumberParticle p = (NumberParticle)it.previous();
// p.kill();
// it.remove();
p.readyToDelete = true;
}
}
4- There is also a button to remove all the NumberParticles at once from the name, it flags all the NumberParticles so they can be remove in the next draw loop
void removeTitleNumbers() {
for (ListIterator it = numbers.listIterator(numbers.size()); it.hasPrevious();) {
NumberParticle p = (NumberParticle)it.previous();
if (p.belongsToTitle) {
// p.kill();
// it.remove();
p.readyToDelete = true;
}
}
}
5- Main draw() here is what happens in the main loop
void draw() {
world.update();
updateNumberParticleProperties();
startPDFexport();
if (showDotToDotLine && !enableSavePDF) {
renderDotToDotLine();
}
renderNumbers(numberTextSize, numberAnchorPointSize);
}
void updateNumberParticleProperties() {
// Update physics world attraction behaviour force radius
for (Iterator b = world.behaviors.iterator(); b.hasNext();) {
AttractionBehavior2D att = (AttractionBehavior2D)b.next();
att.setRadius(repulsiveForceRadius);
}
}
void renderNumbers(int _textSize, float _anchorSize) {
textAlign(CENTER);
textSize(numberTextSize);
for (ListIterator it = numbers.listIterator(); it.hasNext();) {
NumberParticle np = (NumberParticle)it.next();
if (np.readyToDelete) {
np.kill();
it.remove();
}
else {
np.numberTextSize = _textSize;
np.anchorRadius = _anchorSize;
np.render();
}
}
}
void renderDotToDotLine() {
noFill();
stroke(60);
strokeWeight(2);
beginShape();
for (ListIterator<NumberParticle> it = numbers.listIterator(); it.hasNext();) {
VerletParticle2D p = (VerletParticle2D)it.next().anchor;
vertex(p.x, p.y);
}
endShape();
}
So what happens?
The error happens very random when removing NumberParticles, I know I'm iterating in different places for NumberParticles and the VerletPhysics2D particles and springs in different places, and the error seems to be then the physics engine does not sync when I remove elements from it, but I dont know how to bullet proof when I need to delete particles and springs from the simulation
Any help will much appreciated!
Oh here is the error I get:
Caused by: java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.remove(AbstractList.java:357) at DotToDot13.renderNumbers(DotToDot13.java:352) at DotToDot13.draw(DotToDot13.java:187) at processing.core.PApplet.handleDraw(PApplet.java:2305) at processing.opengl.PGL$PGLListener.display(PGL.java:2601) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:588) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:572) at javax.media.opengl.awt.GLCanvas$7.run(GLCanvas.java:1054) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1034) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:909) at javax.media.opengl.awt.GLCanvas$8.run(GLCanvas.java:1065) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:715) at java.awt.EventQueue.access$400(EventQueue.java:82) at java.awt.EventQueue$2.run(EventQueue.java:676) at java.awt.EventQueue$2.run(EventQueue.java:674) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86) at java.awt.EventQueue.dispatchEvent(EventQueue.java:685) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Could not run the sketch (Target VM failed to initialize). Finished.Make sure that you haven't set the maximum available memory too high.
Answers
http://stackoverflow.com/questions/12487915/removing-an-item-from-a-list-using-listiterator
specifically the bit in answer 1 about adding whilst removing (which i think is possible because of the "Particles are created when the user clicks or drag the mouse" thing)
Difficult but you need to separate out the update logic from the rendering logic.
First iI would register the pre method in setup with
registerMethod("pre", this);
and create the method with
void pre(){
}
This method is always executed just before the draw() method so is a great place to update the physics engine.
I also suggest that you have two global lists
NumberParticles can be safely added to these lists from anywhere in the sketch (e.g. mouseClicked, mouseMoved, keyTyped etc) because these lists are only iterated over in the pre method.
The pre method would
(1) iterate over the death list removing each NumberParticle from the Physics engine in turn
(2) iterate over the born list adding each NumberParticle to the physics engine in turn
(3) clear both the death and birth lists
(4) any other updating of NumberParticles (if any)
(5) world.update()
This leaves the draw(0 method the sole responsibility or rendering the particles.
HTH
Interesting! I will give it a shot