Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a simple cubic going crazy #117

Open
abu-irrational opened this issue Sep 5, 2021 · 3 comments
Open

a simple cubic going crazy #117

abu-irrational opened this issue Sep 5, 2021 · 3 comments
Labels

Comments

@abu-irrational
Copy link

it's a just a simple cubic, but for some degenerate cases it takes seconds and gigabytes of memory !

// a simple cubic,
 // it is a degenerate curve for beta 0, PI/2, PI, ...
 // it works for beta = 0.0
 //  BUT for beta = 2*PI    (same curve as for beta = 0)
 //  it uses GigaBYTES !
BLPath mycurve(double R, double beta) {

  BLPath path;
  double x = R*cos(beta);
  double y = R*sin(beta);

  path.moveTo(x,y);
  path.cubicTo(0.0,2*y,  0.0,-2*y,  x,-2*y);

  return path;
}


BLImage render(const BLContextCreateInfo& cci) {
  BLImage img(512, 512, BL_FORMAT_PRGB32);
  BLContext ctx(img, cci);

  ctx.clearAll();

  BLPoint P;
  double R = 200.0;

  // build a path p0  with beta 0.0
  BLPath path0 = mycurve(R, 0.0);

   // for beta=360,  mycurve(R,2*PI)   should be  equal to mycurve(R,0) 
   //  but ...
   //  we have an approx PI ... 

  double PI =3.141592653589793; 
  BLPath path360 = mycurve(R, 2*PI);


  // TEST !!!   repeat 50 times  ... Strace gives <Execution timed out>

  ctx.setStrokeStyle(BLRgba32(0xFFFFFFFF));

  for (int i=0; i< 50; ++i) {
      ctx.strokePath(path0);

    ctx.strokePath(path360);
  }
  return img;
}
@kobalicek kobalicek added the bug label Oct 6, 2021
@kobalicek
Copy link
Member

Should be fixed by 2f79eb2

@abu-irrational
Copy link
Author

Tested your fix: I should say that it's only partially fixed.
The worst cases causing huge processing times are fixed,
but there are still simple (degenerate cubics) that are not drawn.

Consider this cubic
{0,0} ,{200,0}, {200,0}, {0, 0}
it should be rendered as a straight line from (0,0) to (150,0) (and then back to (0,0))
but this curve is not drawn at all.

----- here is a fiddle for testing ----

BLPath mycubic(BLPoint P0, BLPoint P1, BLPoint P2, BLPoint P3) {
BLPath path;

path.moveTo(P0);
path.cubicTo(P1,P2,P3);
return path;
}

BLImage render(const BLContextCreateInfo& cci) {
BLImage img(512, 512, BL_FORMAT_PRGB32);
BLContext ctx(img, cci);

ctx.clearAll();

double width = ctx.targetWidth();
double height = ctx.targetHeight();

// translate origin at center of the screen
ctx.translate(width/2.0,height/2.0);

// draw XY axis 

ctx.setFillStyle(BLRgba32(0xFF808080));
ctx.setStrokeStyle(BLRgba32(0xFF404040));
ctx.strokeLine(0.0,height,0.0,-height);
ctx.strokeLine(-width, 0.0,width,0.0);

// set color for the next cubics ..
ctx.setStrokeStyle(BLRgba32(0xFFFFFFFF));

ctx.strokePath(mycubic( {0,0},{200,0},{200,0},{0, 0} )); // nothing is drawn !!  

// translate the same cubic vertically 
//  then apply a minimal variation to a coord
ctx.translate(0,50);
ctx.strokePath(mycubic( {0,0},{200.001,0},{200,0},{0, 0} ));   // OK

return img;
}

@abu-irrational
Copy link
Author

I'm not sure what I've found regarding degenerate cubics not rendered
such as (0,0) (0,100) (0,100) (0,0)
or more generally cubics like {pA pB pB pA}
but I've found some strange suspicious things in "pathstroke.cpp"

The first thing I noted is at line 288
BLPoint p[7] // ? why 7 ? 4 is enough !
this could be not important (just some unused space on the stack),
but then I noted that
isCubicFlat(..) (at line 299)
on curves like the ones above returns "true".
Is it correct ?
I agree that {pA pB pB pA} are 4 aligned points, but this is not a flat curve,
it's a 'folded' curve starting from pA, going straight to pB, and then going back to pA
..
Anyway, after this isCubicFlat test, this curve is treated as a Line from p0 to the last point p3,
but this is a null segment and so it's skipped.

I could be wrong, I didn't debug the code, just read it, and honestly, I didn't understand the used algorithm,
but this "isCubicFlat()" looks strange to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants