2

I have closed Path-s, which consist of many Bezier segments. These Bezier segments have integer coordinates up to 5000,5000. I need to compute if a point is inside one of these closed Paths. I use this code:

// p is a Path, bounds is a RectF
p.computeBounds(bounds, true);
Region region = new android.graphics.Region();
region.setPath(path, new android.graphics.Region((int)bounds.left, (int)bounds.top, (int)bounds.right, (int)bounds.bottom));

I do that once per Path and then do

region.contains(x, y);

Problem is, that the computeBounds crashes the app for my big Paths. There is no force close, it just receives SIGSEGV and returns to home screen, with no message. I tried to downscale the coordinates to smaller number (divided by 1000), but it did not help, program still crashes.

Is there any other way to compute if a point is inside a complex Path, which will not crash?

EDIT Is there a way to compute this with RenderScript? I cannot find any RenderScript examples with paths/Bezier curves...

EDIT 2 This happens in Nexus 7 with 4.1.1 and also 4.1.2 and also in ICS x86 tablet emulator

shelll
  • 3,234
  • 3
  • 33
  • 67

1 Answers1

4

Normally Java code results in exception rather than segmentation fault, meaning there is something wrong with Java Virtual Machine, unless you have own JNI code in your project and that is causing segmentation fault.

Instead of computing path's bounds, which seems to be too expensive operation for your complex path you can use huge enough clip rectangle to bound all possible paths as clip region so you can avoid calling heavy and unnecessary Path.computeBounds.

import android.graphics.Region;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Rect;

private static final String id = "Graphics";

...

Path path = new Path();
/* Initialize path here... */

/* Huge rectangle to bound all possible paths */
Region clip = new Region(0, 0, 10000, 10000);

/* Define the region */
Region region = new Region();
if (region.setPath(path, clip)) {
    Log.d(id, "This region is fine");
} else {
    Log.e(id, "This region is empty");
}
divanov
  • 6,173
  • 3
  • 32
  • 51
  • I have no native code in my app. I read somewhere else, that setPath and computeBounds can crash like this for big paths. I do not see any difference between our codes. Both define a path, then compute its bounds and after that create a Region and set a path with setPath() or am I missing something? Either way, the application crashes right on the first path.computeBounds(bounds, true); If I remove computeBounds (and of course setPath) the app does not crash. If I remove only setPath, the app crashes. – shelll Oct 17 '12 at 10:51
  • As I said above, you can use huge enough clip rectangle to bound all your possible paths as `clip` so you can avoid calling heavy and unnecessary `computeBounds`. If Dalvik is not capable of processing your path with huge amount of control points, then you should focus on approximating your path with coarser one with smaller amount of points. – divanov Oct 17 '12 at 12:14
  • not computing the bounds of the path and just setting a big enough clip region solved the problem. Program does not crash and the region.contains() is really fast event for this complex paths. Can you edit your answer saying at the beginning, that just use a big enough clip region? I will accept it then. – shelll Oct 18 '12 at 06:09
  • Since you get a segmentation fault instead of an exception, it's worth to be mentioned about possible own JNI code involvement and emphasize this is an exceptional case if there is no own JNI code, which needs non-standard workaround. – divanov Oct 18 '12 at 08:03
  • As I said earlier, I have no own native code. The Path and Region classes use native code for many things themself. Funny thing is, that it cannot compute bounds but computes if a point is inside the closed path without any problems, which is a more demanding task. Tahnk you again. – shelll Oct 18 '12 at 08:10