What's the right way to delete a Chipmunk body? Simply calling cpBodyFree or cpBodyDestroy doesn't seem to work, as the body still shows up in the cpSpaceEachBody iteration.
if(body->p.y < -260 || fabsf(body->p.x) > 340) {
/* body is permanently off the screen */
/* so it needs to be permanently deleted */
cpBodyFree(body); ??
cpBodyDestroy(body); ??
}
Here's how to delete a body:
if there's a shape associated with the body, remove the shape from the space and delete it.
remove the body from the space. (this is the part I was missing.)
finally, delete the space if it is not needed anymore.
Here's how to make the Plink demo rain down a single shower of pentagons and clean them up when
they go off screen.
Add this line to the "//Add lots of pentagons" loop. This is so we can free the shape attached to the body.
body->data=shape;
remove the shape and body from the space, then free the shape and body. It doesn't
seem to matter if you remove/free the shape first or the body first, so long as you
keep in mind that you lose the pointer to the shape when you free the body. Change the eachBody function to:
if (body->p.y < -260 ) {
cpSpaceRemoveShape(space, body->data);
cpSpaceRemoveBody(space, body);
cpShapeFree(body->data);
cpBodyFree(body);
}
After looking in the lib code
void cpBodyDestroy(cpBody *body){}
void
cpBodyFree(cpBody *body)
{
if(body){
cpBodyDestroy(body);
cpfree(body);
}
}
Call cpBodyFree (it calls internally cpBodyDestroy internally.
UPDATE: Except in cases where you don't need the validation and the cpfree(body) call ; )
you have to make sure whether the shape has been added as static or not, may be this code will help a bit:
if(shape != NULL)
{
int isStatic = 1;
cpBody *bd = cpShapeGetBody(shape);
if(bd != NULL)
{
if(!cpBodyIsRogue(bd) && !cpBodyIsStatic(bd)) //second condition is just to make sure
{
isStatic = 0;
cpSpace *sp1 = cpBodyGetSpace(bd);
if(sp1 != NULL)
{
cpSpaceRemoveBody(sp1, bd); //remove body from space and then free it
}
}
cpBodyFree(bd);
}
cpSpace *sp = cpShapeGetSpace(shape);
if(sp != NULL)
{
if(isStatic)
cpSpaceRemoveStaticShape(sp, shape);
else
cpSpaceRemoveShape(sp, shape); //remove shape from space and then free it
}
cpShapeFree(shape);
shape = NULL;
}
Related
I get a Null Pointer Exception, and the trace tells me it is inside a function that I have. This function runs every frame and does some calculations and stuff. Anyway, the problem is that when I go to debug, stepping through each line, the function runs fine, and the error only comes up at the end of the draw loop.
This error only recently came up, and the changes I made don't have much to do with the function in question so...
The function mentioned in the trace detects if the object touches something, and acts on it.
Also, the trace gives a line number that does not exist, I'm guessing that's because of the Processing compiling.
I am using Processing 4 if that matters.
Here's the trace:
java.lang.NullPointerException
at ants$Ant.sense(ants.java:190)
at ants$Ant.go(ants.java:220)
at ants.draw(ants.java:44)
at processing.core.PApplet.handleDraw(PApplet.java:2201)
at processing.awt.PSurfaceAWT$10.callDraw(PSurfaceAWT.java:1422)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:354)
Thanks!
Edit:
More info: This is an ant simulator, and it crashes at food pickup. This used to work and broke while adding (seemingly) unrelated stuff. It crashes at food pickup, which is managed by the sense() function. The Food class only has a position and a render function.
Here is some code:
void sense() { // The problematic function
if (!detectFood && !carryFood) {
float closest = viewRadius;
Food selected = null;
for (Food fd : foods){
float foodDist = position.dist(fd.position);
if(foodDist <= viewRadius) {
if(foodDist < closest) {
selected = fd;
closest = foodDist;
}
}
}
if (selected != null){
detectFood = true;
foodFocused = selected;
}
} else {
if(position.dist(foodFocused.position) < 2*r) {
takeFood();
detectFood = false;
}
}
}
void draw() { // draw loop
background(51);
for (Food food : foods) {
food.render();
}
for (Ant ant : ants) {
ant.go();
}
for (int i=0; i < trails.size(); i++) {
Trail trail = trails.get(i);
if (trail.strenght <= 0)
trails.remove(trail);
else
trail.go();
}
}
The problem is not the trail, as it still crashes without it,
I am getting the below error while trying to redact pdf document using itext7
I am calling pdfCleanupTool.cleanup() method for redaction and sometimes I am getting the below error from the cleanup method:
Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index
Any help appreciated.
Thanks!
Updates:
Error Log:
There is a bug in the iText 7 PdfTextArray class which generates stack traces like yours. As you don't share your PDF, though, I cannot be sure whether that's the bug bothering you currently.
The Bug
The bug can be provoked quite easily, in Java like this
PdfTextArray textArray = new PdfTextArray();
textArray.add(1);
textArray.add(-1);
textArray.add(1);
(CancelingAdjustments test testCancelingAdjustments)
and similarly in C#.
This essentially may be what happens in the OP's case; redaction involves removal of text pieces from such text arrays and replacement by equivalent numeric adjustments, so such situations may be more probable during redaction than in general.
The Cause
When adding multiple numbers to a PdfTextArray, it attempts to combine them to a single number, and if that single number is zero, remove it altogether:
public boolean add(float number) {
// adding zero doesn't modify the TextArray at all
if (number != 0) {
if (!Float.isNaN(lastNumber)) {
lastNumber = number + lastNumber;
if (lastNumber != 0) {
set(size() - 1, new PdfNumber(lastNumber));
} else {
remove(size() - 1);
}
} else {
lastNumber = number;
super.add(new PdfNumber(lastNumber));
}
lastString = null;
return true;
}
return false;
}
(PdfTextArray method add)
But this code forgets to reset the lastNumber variable to "not a number" after removal due to cancelation. Thus, this bug can be fixed like this:
public boolean add(float number) {
// adding zero doesn't modify the TextArray at all
if (number != 0) {
if (!Float.isNaN(lastNumber)) {
lastNumber = number + lastNumber;
if (lastNumber != 0) {
set(size() - 1, new PdfNumber(lastNumber));
} else {
remove(size() - 1);
lastNumber = Float.NaN;
}
} else {
lastNumber = number;
super.add(new PdfNumber(lastNumber));
}
lastString = null;
return true;
}
return false;
}
(One could improve this some more by testing whether there is some string at the now last position of the array and initialize lastString accordingly.)
The iText/.Net code is very similar here.
I've read somewhere that a variable should be entered into the code if it is reused. But when I write my code for logic transparency, I sometimes create intermediate variables (with names reflecting what they contain) which are used only once.
How incorrect is this concept?
PS:
I want to do it right.
It is important to note that most of the time clarity takes precedence over re-usability or brevity. This is one of the basic principles of clean code. Most modern compilers optimize code anyway so creating new variables need not be a concern at all.
It is perfectly fine to create a new variable if it would add clarity to your code. Make sure to give it a meaningful name. Consider the following function:
public static boolean isLeapYear(final int yyyy) {
if ((yyyy % 4) != 0) {
return false;
}
else if ((yyyy % 400) == 0) {
return true;
}
else if ((yyyy % 100) == 0) {
return false;
}
else {
return true;
}
}
Even though the boolean expressions are used only once, they may confuse the reader of the code. We can rewrite it as follows
public static boolean isLeapYear(int year) {
boolean fourth = year % 4 == 0;
boolean hundredth = year % 100 == 0;
boolean fourHundredth = year % 400 == 0;
return fourth && (!hundredth || fourHundredth);
}
These boolean variables add much more clarity to the code.
This example is from the Clean Code book by Robert C. Martin.
I'm trying to use join_facet() iteratively to grow a single facet starting from a given facet_handle. However, I'm running into trouble when using the Halfedge_around_facet_circulator in combination with join_facet(). My while-loop does not become false anymore which works fine if I don't use join_facet() and the circulator seems to point to something else.
I assume that the join operation is somehow changing that Halfedge_around_facet_circulator. But why and how to solve this?
Polyhedron P_out; // is a valid pure triangle Polyhedron
bool merge_next = true;
while (merge_next == true) {
Polyhedron::Halfedge_around_facet_circulator hit = facet_handle->facet_begin(); // facet_handle pointing to facet of P_out
merge_next = false;
do {
if(!(hit->is_border_edge())) {
if (coplanar(hit->facet(), hit->opposite()->facet())) {
if (CGAL::circulator_size(hit->opposite()->vertex_begin()) >= 3 && CGAL::circulator_size(hit->vertex_begin()) >= 3
&& hit->facet()->id() != hit->opposite()->facet()->id()) {
Polyhedron::Halfedge_handle hit2 = hit;
P_out->join_facet(hit2);
merge_next = true;
}
}
}
} while (++hit != facet_handle->facet_begin());
}
What this code should do:
Given the facet_handle, iterate over the corresponding halfedges of facet and merge if possible. Then taking facet_handle of created new facet again and doing the same until no neighboring facets are left to merge.
Edit:
There are areas on which the code runs fine and others where it crashes at hit->is_border_edge() after the first join_facet().
I'm messing around with the PushSource sample filter shipped with the DirectShow SDK and I'm having the following problem:
When I call IMediaControl::Run(), it returns S_FALSE which means "the graph is preparing to run, but some filters have not completed the transition to a running state". MSDN suggests to then call IMediaControl::GetState() and wait for the transition to finish.
And so, I call IMediaControl::GetState(INFINITE, ...) which is supposed to solve the problem.
However, to the contrary, it returns VFW_S_STATE_INTERMEDIATE even though I've specified an infinite waiting time.
I've tried all three variations (Bitmap, Bitmap Set and Desktop) and they all behave the same way, which initially lead me to believe there is a bug in there somewhere.
However, then, I tried using IFilterGraph::AddSourceFilter to do the same and it did the same thing, which must mean it's my rendering code that is the problem:
CoInitialize(0);
IGraphBuilder *graph = 0;
assert(S_OK == CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&graph));
IBaseFilter *pushSource = 0;
graph->AddSourceFilter(L"sample.bmp", L"Source", &pushSource);
IPin *srcOut = 0;
assert(S_OK == GetPin(pushSource, PINDIR_OUTPUT, &srcOut));
graph->Render(srcOut);
IMediaControl *c = 0;
IMediaEvent *pEvent;
assert(S_OK == graph->QueryInterface(IID_IMediaControl, (void**)&c));
assert(S_OK == graph->QueryInterface(IID_IMediaEvent, (void**)&pEvent));
HRESULT hr = c->Run();
if(hr != S_OK)
{
if(hr == S_FALSE)
{
OAFilterState state;
hr = c->GetState(INFINITE, &state);
assert(hr == S_OK );
}
}
long code;
assert(S_OK == pEvent->WaitForCompletion(INFINITE, &code));
Anyone knows how to fix this?
IBaseFilter *pushSource = 0;
graph->AddSourceFilter(L"sample.bmp", L"Source", &pushSource);
AddSourceFilter adds a default source filter, I don't think it will add your pushsource samplefilter.
I would recommend to add the graph to the ROT, so you can inspect it with graphedit.
And what happens if you don't call GetState()?
hr = pMediaControl->Run();
if(FAILED(hr)) {
/// handle error
}
long evCode=0;
while (evCode == 0)
{
pEvent->WaitForCompletion(1000, &evCode);
/// other code
}
Open GraphEditPlus, add your filter, render its pin and press Run. Then you'll see states of each filter separately, so you'll see what filter didn't run and why.