【问题标题】:processing sketch throwing java.lang.AssertionError only when fill() is used仅在使用 fill() 时处理引发 java.lang.AssertionError 的草图
【发布时间】:2019-11-17 00:41:38
【问题描述】:

研究项目是关于使用几何库从 .ttf 类型的字体文件中获取形状的过程中沿贝塞尔曲线(递归多项式形式)扭曲文本。(它需要数据目录中的 ttf 文件才能运行。)目前,草图似乎在 填充(任何颜色);用于代码绘制字符形状并且贝塞尔曲线的长度小于一定长度的部分。如果填充();未使用,草图似乎可以正常运行,没有任何错误。 目标是使用 fill();函数来填充字符而不会出错。

我试过了; 1) 摆脱 beginContour();和 endContour();因为我认为它没有正确编写。(我认为这是错误的,因为轮廓应该只在形状是字母的内侧时绘制,但目前,它在不是第一个或最后一个形状时绘制轮廓)但是即使未使用轮廓函数(使用了填充();),草图也会引发错误。 2)认为它与曲线的长度有关,因此尝试在绘制字母的部分添加if语句。到目前为止,我已经尝试使用从 void setup(){} 中的初始字体大小和字符串生成的 RGroup 的宽度以及贝塞尔曲线的长度。 if 语句中的条件示例如下; - 当 RGroup 形状的宽度小于曲线的长度时绘制字母 - 当“缩进”(计算曲线上位置的变量)值小于曲线长度时绘制字母。 (此案例使草图仅在字母放在曲线内时才绘制字母,但仍然出现错误) -当“缩进”(计算曲线上位置的变量)值小于RGroup的宽度时绘制字母。

我没有看到问题到底发生在哪里,所以我在草图中分享了整个代码,但我用“//******”标记了我认为错误发生的地方*"。

这项研究基于以下link。 几何库文档可以从以下link看到。

//build a bezier curve using the recursive polynomial form
//number of control points(num+1 points)
int num = 4;
//arraylist to store the picked values
ArrayList<Point> pt;
float nfac;

import geomerative.*;

RFont fnt;
RGroup rg;
RPoint [][]rp;

String str = "(O_o)/ Oooh";

FloatList X;
FloatList Y;
FloatList SUM;

void setup(){
  size(1000,1000,P2D);
  RG.init(this);
  pt = new ArrayList<Point>();
  //pick a number of points with random positions and store x,y values in them
  for(int i=0; i<=num; i++){
    float x = random(0,width);
    float y = random(0,height);
    pt.add(new Point(x,y));
  }

  fnt = new RFont("Zapfino.ttf",100);
  //RCommand.setSegmentAngle(random(0,HALF_PI)); 
  //RCommand.setSegmentator(RCommand.ADAPTATIVE);
  RCommand.setSegmentLength(3); 
  RCommand.setSegmentator(RCommand.UNIFORMLENGTH);

  rg = fnt.toGroup(str);
  rp = rg.getPointsInPaths();

  X = new FloatList();
  Y = new FloatList();

  SUM = new FloatList();
}

void draw(){
  background(255);
  noFill();
  strokeCap(ROUND);
  strokeWeight(2);
  //draw points
  beginShape();
  for(int i=0; i<=num; i++){
    vertex(pt.get(i).x,pt.get(i).y);
  }
  endShape();

  for(int i=0; i<=num; i++){
    ellipse(pt.get(i).x,pt.get(i).y,10,10);
  }


  //draw curve
  nfac = 1;
  for(int i=0; i<num; i++){
    nfac *= (i+1);
  }

  strokeWeight(2);
  beginShape();
  int Bzindex = 0;
  for(float t=0; t<=1; t+=0.01){
    float x = 0;
    float y = 0;
    Bzindex++;
    for(int i=0; i<=num; i++){

      float coef = 1;
      float kfac = 1;
      float k_nfac = 1;
      for(int k=i; k>0; k--){
        kfac *= k;
      }
      for(int k=(num-i); k>0; k--){
        k_nfac *= k;
      }

      coef = nfac/(kfac*k_nfac);

      x += coef*(pow((1-t),num-i)*pow(t,i)*pt.get(i).x);
      y += coef*(pow((1-t),num-i)*pow(t,i)*pt.get(i).y);

    }
    vertex(x,y);
    X.set(Bzindex,x);
    Y.set(Bzindex,y);
  }
  endShape();




  //get arclength by pulling points from a floatlist
  int numberOfDivisions = X.size()-2;
  int maxPoint = numberOfDivisions+1;

  float sum = 0;

  float prevPointX = X.get(0);
  float prevPointY = Y.get(0);

  for(int i=1; i<=maxPoint; i++){
    float pointX = X.get(i);
    float pointY = Y.get(i);
    sum += dist(pointX,pointY,prevPointX,prevPointY);
    SUM.set(i-1,sum);
    prevPointX = pointX;
    prevPointY = pointY;
  }
  //

  //*******************************************************
  noFill();
  //creates error only when using fill();
  fill(0,255,0);
  stroke(0);
  //noStroke();
  strokeWeight(4);
  float indent = SUM.get(0);
  beginShape();
  for(int i=0; i<rp.length; i++){

    if(i>0){
      beginContour();
    }

    for(int j=0; j<rp[i].length; j++){
      float t = 0;

      indent = rp[i][j].x+SUM.get(0);

      //

      float targetArcLength = indent;

        int index = IndexOfLargestValueSmallerThan(targetArcLength);

        if(SUM.get(index)==targetArcLength){
          t = index/(SUM.size()-1);
        }else{
          float lengthBefore = SUM.get(index);
          float lengthAfter = SUM.get(index+1);
          float segmentLength = lengthAfter - lengthBefore;
          float segmentFraction = (targetArcLength - lengthBefore)/segmentLength;
          t = (index+segmentFraction)/(SUM.size()-1);
        }

        float x = 0;
        float y = 0;
        float vx = 0;
        float vy = 0;

          for(int l=0; l<=num; l++){

            float coef = 1;
            float kfac = 1;
            float k_nfac = 1;
            for(int k=l; k>0; k--){
              kfac *= k;
            }
            for(int k=(num-l); k>0; k--){
              k_nfac *= k;
            }

            coef = nfac/(kfac*k_nfac);

            x += coef*(pow((1-t),num-l)*pow(t,l)*pt.get(l).x);
            y += coef*(pow((1-t),num-l)*pow(t,l)*pt.get(l).y);

            float v = (pow(1-t,num-l)*l*pow(t,l-1))+((num-l)*pow(1-t,num-l-1)*(-1)*pow(t,l));
            vx += coef*pt.get(l).x*(v);
            vy += coef*pt.get(l).y*(v);
         }

        PVector P = new PVector(x,rp[i][j].y+y);

        PVector ldir = new PVector(P.x-x,P.y-y);


        PVector dir = new PVector(vy,-vx); 
        //
        ldir.rotate(dir.heading()+PI/2);

        vertex(x+ldir.x,y+ldir.y);
      }
      if(i<rp.length&&i>0){
        endContour();
      }

    }
    endShape();
    //**************************************************************
}

int IndexOfLargestValueSmallerThan(float _targetArcLength){
  int index = 0;
  for(int i=0; i<SUM.size()-1; i++){
    if(SUM.get(i)<=_targetArcLength){
      index = i;
    }
  }
  return index;
}

void mouseDragged(){
  int which = -1;
  if((mouseX<width)&&(mouseX>0)&&(mouseY<height)&&(mouseY>0)){
  for(int i=0; i<=num; i++){
    if(dist(mouseX,mouseY,pt.get(i).x,pt.get(i).y)<50){
      which = i;
      pt.get(which).update(mouseX,mouseY);
    }
  }
  }
}

class Point{
  float x,y;

  Point(float _x, float _y){
    x = _x;
    y = _y;
  }

  void update(float _newx, float _newy){
    x = _newx;
    y = _newy;
  }

}

加载草图时有时会发生错误。大多数情况下,它加载正常,但是当您稍微拖动点时会引发错误。错误代码有时是指通过鼠标位置更新曲线控制点的点,但由于加载草图时也会发生错误,我认为不是与更新位置有关的问题。

错误代码如下;

a.lang.AssertionError
    at processing.opengl.PSurfaceJOGL$2.run(PSurfaceJOGL.java:412)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.AssertionError
    at jogamp.opengl.glu.tessellator.Sweep.AddRightEdges(Sweep.java:358)
    at jogamp.opengl.glu.tessellator.Sweep.SweepEvent(Sweep.java:1105)
    at jogamp.opengl.glu.tessellator.Sweep.__gl_computeInterior(Sweep.java:1339)
    at jogamp.opengl.glu.tessellator.GLUtessellatorImpl.gluTessEndPolygon(GLUtessellatorImpl.java:526)
    at com.jogamp.opengl.glu.GLU.gluTessEndPolygon(GLU.java:896)
    at processing.opengl.PJOGL$Tessellator.endPolygon(PJOGL.java:641)
    at processing.opengl.PGraphicsOpenGL$Tessellator.tessellatePolygon(PGraphicsOpenGL.java:12621)
    at processing.opengl.PGraphicsOpenGL.tessellate(PGraphicsOpenGL.java:2255)
    at processing.opengl.PGraphicsOpenGL.endShape(PGraphicsOpenGL.java:1965)
    at processing.core.PGraphics.endShape(PGraphics.java:1707)
    at processing.core.PApplet.endShape(PApplet.java:11641)
    at bezier_polynomial_recursive_text_03.draw(bezier_polynomial_recursive_text_03.java:218)
    at processing.core.PApplet.handleDraw(PApplet.java:2475)
    at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:866)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
RuntimeException: java.lang.AssertionError
    at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
    at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759)
    at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
    at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
    at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

【问题讨论】:

  • 您可能在堆栈上的内存不足。如果是这样,最有可能的罪魁祸首就是疯狂的二维数组rp。在一个类中切换它(创建你自己的或使用像 ArrayList 这样的容器数组)会在堆上切换它的大部分。这需要一些工作,虽然我可能错了,但这是我要尝试的第一件事。
  • 感谢您的建议!我会试一试,让你知道它是否顺利。我认为很有可能内存不足也是我在使用 fill() 函数时遇到问题的原因,因为当我关闭 P2D 渲染器时,草图没有抛出任何错误。
  • 让我更新,就我而言,这是一个有趣的问题!
  • 我摆脱了错误,但仍然对问题所在不自信..!!主要问题似乎是数学公式写得不好。
  • As is mentioned on the wikipedia page about bezier curves, this way of computing is not recommended. 这让我笑了!顺便恭喜你,你可能成功了。我很高兴我能见证它!

标签: java processing


【解决方案1】:

我认为这不会直接回答我的问题,但它确实阻止了在同时使用 fill() 和 P2D 渲染器时发生错误。正如上面 laancelot 所指出的,主要问题确实似乎与堆栈溢出有关。所以我用下面写的两种方式解决了这个问题;结论:直接原因是数学公式表达不佳。

1) 在类内切换 RPoints。 - 我不认为这是发生错误的直接原因,因为在仅完成这部分代码重写的阶段,错误仍然存​​在。但也许这是问题的一部分。我不确定。

2) 重写代码表达公式的部分,以评估特定点的贝塞尔曲线。 - 以前,公式是通过使用 n 次贝塞尔曲线的显式定义来制定的。因此,必须为 RPoint 点中的每个点计算(更像是制定)公式。正如关于贝塞尔曲线的维基百科页面所提到的,不推荐这种计算方式。 -在修改后的代码中,用于扭曲文本的公式以多项式形式表示。因此,它能够在迭代 RPoint 点之前预先计算多项式的系数。这似乎解决了问题。

我仍然不确定到底是什么导致了这个问题,为什么它已经解决了,我应该展示代码的哪一部分来向其他人解释这个问题,所以我将分享整个重写的代码.您需要处理、几何库和数据文件夹中的 ttf 类型字体文件来测试代码。我已经标记了涉及公式修订版的地方。 (还是很乱……)

//n number of points
int num = 4;
//arraylist to store the picked values
ArrayList<cntrlPoint> pt;

//import the geomerative library
import geomerative.*;



//string
String str = "(O_o)/ Oooh";

FloatList X;
FloatList Y;
FloatList SUM;

RClass rc;

void setup() {
  size(1000, 1000, P2D);
  pt = new ArrayList<cntrlPoint>();
  //pick a number of points with random positions
  for (int i=0; i<=num; i++) {
    float x = random(0, width);
    float y = random(0, height);
    pt.add(new cntrlPoint(x, y));
  }

  RG.init(this);
  rc = new RClass();   

  X = new FloatList();
  Y = new FloatList();  
  SUM = new FloatList();
}

void draw() {
  background(255);
  noFill();
  strokeWeight(2);
  drwCntrlPoints();
  drwCurve();
  gtArcLength();
  fill(0,255,0);
  rc.crtPoly(pt);
  rc.drwText();
}

void drwCntrlPoints() {
  //draw points
  beginShape();
  for (int i=0; i<=num; i++) {
    vertex(pt.get(i).x, pt.get(i).y);
  }
  endShape();

  for (int i=0; i<=num; i++) {
    ellipse(pt.get(i).x, pt.get(i).y, 10, 10);
  }
}

void drwCurve() {
  //draw curve
  float curveDetail = 0.01;
  float nfac = 1;
  for (int i=0; i<num; i++) {
    nfac *= (i+1);
  }
  int arcIndex = 0;
  strokeWeight(2);
  beginShape();
  for (float t=0; t<=1; t+=curveDetail) {
    float x = 0;
    float y = 0;
    arcIndex++;
    for (int i=0; i<=num; i++) {

      float coef = 1;
      float kfac = 1;
      float k_nfac = 1;
      for (int k=i; k>0; k--) {
        kfac *= k;
      }
      for (int k=(num-i); k>0; k--) {
        k_nfac *= k;
      }

      coef = nfac/(kfac*k_nfac);

      x += coef*(pow((1-t), num-i)*pow(t, i)*pt.get(i).x);
      y += coef*(pow((1-t), num-i)*pow(t, i)*pt.get(i).y);
    }
    vertex(x, y);
    X.set(arcIndex, x);
    Y.set(arcIndex, y);
  }
  endShape();
}

void gtArcLength() {
  //get arclength by pulling points from a floatlist
  int numberOfDivisions = X.size()-2;
  int maxPoint = numberOfDivisions+1;

  float sum = 0;

  float prevPointX = X.get(0);
  float prevPointY = Y.get(0);

  for (int i=1; i<=maxPoint; i++) {
    float pointX = X.get(i);
    float pointY = Y.get(i);
    sum += dist(pointX, pointY, prevPointX, prevPointY);
    SUM.set(i-1, sum);
    prevPointX = pointX;
    prevPointY = pointY;
  }
}

//*******factorial
int fact(int fa){
  if(fa==1){
    return 1;
  }
  if(fa==0){
    return 1;
  }
  else{
    return fa*fact(fa-1);
  }
}
//********************

int IndexOfLargestValueSmallerThan(float _targetArcLength) {
  int index = 0;
  for (int i=0; i<SUM.size()-1; i++) {
    if (SUM.get(i)<=_targetArcLength) {
      index = i;
    }
  }
  return index;
}

void mouseDragged() {
  int which = -1;
  if ((mouseX<width)&&(mouseX>0)&&(mouseY<height)&&(mouseY>0)) {
    for (int i=0; i<=num; i++) {
      if (dist(mouseX, mouseY, pt.get(i).x, pt.get(i).y)<80) {
        which = i;
      }
    }
    if (which>-1) {
      pt.get(which).update(mouseX, mouseY);
    }
  }
}

class RClass {
  //get ttf file
  //create rfont
  RFont fnt;
  //turn rfont to rgroup to get points
  RGroup rg;
  //going to get point in path, so that the characters in the string can be seperated
  RPoint [][]rp;

  //floatlist to store coefficients
  FloatList Cx;
  FloatList Cy;

  RClass() {
    fnt = new RFont("Zapfino.ttf", 100);
    rg = fnt.toGroup(str);
    rp = rg.getPointsInPaths();

    //RCommand.setSegmentAngle(random(0,HALF_PI)); 
    //RCommand.setSegmentator(RCommand.ADAPTATIVE);
    RCommand.setSegmentLength(3); 
    RCommand.setSegmentator(RCommand.UNIFORMLENGTH);

    Cx = new FloatList();
    Cy = new FloatList();
  }

  //**********************************here
  void crtPoly(ArrayList<cntrlPoint> _pt){
    float ptsize = _pt.size();
    for(int j=0; j<ptsize; j++){
      float coefx = 0;
      float coefy = 0;
      float pi = 1;
      float sigx = 0;
      float sigy = 0;
      for(int m=0; m<=j-1; m++){
        pi *= (ptsize-1-m);
      }
      for(int i=0; i<=j; i++){
        sigx += (pow(-1,i+j)*pt.get(i).x)/(fact(i)*fact(j-i));
        sigy += (pow(-1,i+j)*pt.get(i).y)/(fact(i)*fact(j-i));
      }
      coefx = pi*sigx;
      coefy = pi*sigy;
      Cx.set(j,coefx);
      Cy.set(j,coefy);
    }
  }
  //**************************************

  void drwText() {
    float indent = SUM.get(0);  

    beginShape();       
    for (int i=0; i<rp.length; i++) {
      if(i>0){
        beginContour();
      }
      for (int j=0; j<rp[i].length; j++) {

        float t = 0;

        indent = rp[i][j].x+SUM.get(0);

        float targetArcLength = indent;

        int index = IndexOfLargestValueSmallerThan(targetArcLength);

        if (SUM.get(index)==targetArcLength) {
          t = index/(SUM.size()-1);
        } else {
          float lengthBefore = SUM.get(index);
          float lengthAfter = SUM.get(index+1);
          float segmentLength = lengthAfter - lengthBefore;
          float segmentFraction = (targetArcLength - lengthBefore)/segmentLength;
          t = (index+segmentFraction)/(SUM.size()-1);
        }

        //***************************here
        float x = 0;
        float y = 0;
        float vx = 0;
        float vy = 0;

        for(int l=0; l<=num; l++){
          x += Cx.get(l)*pow(t,l);
          y += Cy.get(l)*pow(t,l);
        }

        for(int l=1; l<=num; l++){
          vx += l*Cx.get(l)*pow(t,l-1);
          vy += l*Cy.get(l)*pow(t,l-1);
        }
        //**************************************

        PVector P = new PVector(x, rp[i][j].y+y);

        PVector ldir = new PVector(P.x-x, P.y-y);


        PVector dir = new PVector(vy, -vx); 
        //
        ldir.rotate(dir.heading()+PI/2);

        vertex(x+ldir.x, y+ldir.y);
      }
      if(i>0&&i<rp.length){
        endContour();
      }
    }
    endShape();
  }
}

class cntrlPoint{
  float x,y;

  cntrlPoint(float _x, float _y){
    x = _x;
    y = _y;
  }

  void update(float _newx, float _newy){    
    x = _newx;
    y = _newy;   
  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多