【发布时间】: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