在 jsxgraph 中,为什么不通过同一平面上的五个点绘制抛物线?
In jsxgraph, why doesn't a parabola get drawn through five points on a same plane?
在 中,我一直在寻找一种在 3D 中绘制点的方法 space,以便这些点将根据滑块值移动。现在可以了,但是我试图通过这些点绘制的圆锥曲线(在本例中为抛物线)未绘制。
我认为元素 "conic" 的构造函数可能对给定点的定义方式很挑剔,所以我最终添加了作为属性 "sub-objects" 的点,这些点可以在绘制二次曲线。
在我下面的代码中,构造函数 PPoint 创建了具有各自属性 pcoord 的对象,这是一个类型的几何对象"point" 使用本机 jsxgraph 构造函数创建点。当调用方法 "draw" 绘制点 I_1-I-4 和 p_1.
时,会分配 pcoord
在代码的最后几行中,抛物线应该参考对象I_1-I_4和p_1的p坐标来绘制,但是对于由于某些原因未绘制抛物线。
如何解决这个问题? Link to jsfiddle。调试时代码执行无错误通知。
HTML
<div id="jxgbox" class="jxgbox" style="width:500px; height:500px">
</div>
JS
const board = JXG.JSXGraph.initBoard('jxgbox', {
boundingbox: [-10, 10, 10, -10],
axis: true,
showCopyright: true,
showNavigation: true,
pan: false,
grid: false,
zoom: {
factorX: 1.25,
factorY: 1.25,
wheel: false
}
});
//create z axis
var zAxis = board.create('axis', [
[0, 0],
[-1, -1]
], {
ticks: {
majorHeight: 10,
drawLabels: false
}
});
//create direction of view for projections
var cam = [4, 4, 30]; // [x,y,z]
var r = 6.0;
var origin = [0, 0, 0];
// Function for parallel projection
var project = function(crd, cam) {
var d = -crd[2] / cam[2];
return [1, crd[0] + d * cam[0], crd[1] + d * cam[1]];
};
//create slider for rotating the parabola
var sRadius = board.create('slider', [
[1, -8.5],
[6, -8.5],
[-10, 0, 10]
], {
name: 'angle',
needsRegularUpdate: true
//snapWidth: 1
});
//create slider for adjusting the angular speed
var sOmega = board.create('slider', [
[1, -7.5],
[6, -7.5],
[0, 0, 10]
], {
name: 'Omega',
needsRegularUpdate: true
//snapWidth: 1,
});
//fix parameters
const g = 9.81 //gravitational acceleration
const h0 = 5 //initial height of the water surface
//define radius from the y-axis for I3 and I4
const R34 = Math.sqrt(2);
// Function for parallel projection
var project = function(crd, cam) {
var d = -crd[2] / cam[2];
return [1, crd[0] + d * cam[0], crd[1] + d * cam[1]];
};
//function creates points for drawing conic sections
function PPoint(radius, sign, namep, fixval) {
this.R = radius;
this.S = sign;
this.Namep = namep;
this.Fixval = fixval;
this.pcoord = undefined; //Cartesian coordinates of the point, stored as a point
}
//method for drawing each Point
PPoint.prototype.draw = function(pp) {
board.create('point', [function() {
var K1 = sOmega.Value() * sOmega.Value() / g,
KK = 1 / 4 * sOmega.Value() * sOmega.Value() / g,
v = sRadius.Value() * Math.PI * 0.5 / 10.0,
c = [pp.S * pp.R * Math.sin(v), K1 / 2 * pp.R * pp.R - KK + h0, pp.S * pp.R * Math.cos(v)];
//store the dynamically assigned coordinates of the point for drawing the parabola
pp.pcoord = board.create('point', [function() {
return project(c, cam);
}], {
visible: false
}); //end storing pp.coord
return project(c, cam);
}], {
fixed: this.Fixval,
name: this.Namep,
visible: true
})
}
//create and draw points
var p_1 = new PPoint(0, -1, 'p_1', 'false');
var I_1 = new PPoint(r, 1, 'I_1', 'false');
var I_2 = new PPoint(r, -1, 'I_2', 'false');
var I_3 = new PPoint(R34, 1, 'I_3', 'false');
var I_4 = new PPoint(R34, -1, 'I_4', 'false');
p_1.draw(p_1)
I_1.draw(I_1)
I_2.draw(I_2)
I_3.draw(I_3)
I_4.draw(I_4)
//draw the rotating parabola
var prbl = board.create('conic', [I_1.pcoord, I_2.pcoord, I_3.pcoord, I_4.pcoord, p_1.pcoord], {
strokeColor: '#CA7291',
strokeWidth: 2,
trace :true
});
//debugger
这段代码有两个问题:
1) 在 PPoint.draw
中,引用两个 JSXGraph 点不起作用:在每次更新中都会创建一个新的 JSXGraph 点。这会使代码变慢,而且不会影响提供给圆锥曲线的初始点。我建议将 draw
更改为:
PPoint.prototype.draw = function(pp) {
pp.pcoord = board.create('point', [function() {
var K1 = sOmega.Value() * sOmega.Value() / g,
KK = 1 / 4 * sOmega.Value() * sOmega.Value() / g,
v = sRadius.Value() * Math.PI * 0.5 / 10.0,
c = [pp.S * pp.R * Math.sin(v),
K1 / 2 * pp.R * pp.R - KK + h0,
pp.S * pp.R * Math.cos(v)];
return project(c, cam);
}], {
fixed: this.Fixval,
name: this.Namep,
visible: true});
2) 第二个问题是 JSXGraph 无法通过五个点绘制退化二次曲线,并且如果二次曲线接近退化(一般抛物线存在数值问题),则精度会受到影响。此处的起始值 omega = 0
就是这种情况。
这是一个工作示例:https://jsfiddle.net/L2d4zt8q/
在
我认为元素 "conic" 的构造函数可能对给定点的定义方式很挑剔,所以我最终添加了作为属性 "sub-objects" 的点,这些点可以在绘制二次曲线。
在我下面的代码中,构造函数 PPoint 创建了具有各自属性 pcoord 的对象,这是一个类型的几何对象"point" 使用本机 jsxgraph 构造函数创建点。当调用方法 "draw" 绘制点 I_1-I-4 和 p_1.
时,会分配 pcoord在代码的最后几行中,抛物线应该参考对象I_1-I_4和p_1的p坐标来绘制,但是对于由于某些原因未绘制抛物线。
如何解决这个问题? Link to jsfiddle。调试时代码执行无错误通知。
HTML
<div id="jxgbox" class="jxgbox" style="width:500px; height:500px">
</div>
JS
const board = JXG.JSXGraph.initBoard('jxgbox', {
boundingbox: [-10, 10, 10, -10],
axis: true,
showCopyright: true,
showNavigation: true,
pan: false,
grid: false,
zoom: {
factorX: 1.25,
factorY: 1.25,
wheel: false
}
});
//create z axis
var zAxis = board.create('axis', [
[0, 0],
[-1, -1]
], {
ticks: {
majorHeight: 10,
drawLabels: false
}
});
//create direction of view for projections
var cam = [4, 4, 30]; // [x,y,z]
var r = 6.0;
var origin = [0, 0, 0];
// Function for parallel projection
var project = function(crd, cam) {
var d = -crd[2] / cam[2];
return [1, crd[0] + d * cam[0], crd[1] + d * cam[1]];
};
//create slider for rotating the parabola
var sRadius = board.create('slider', [
[1, -8.5],
[6, -8.5],
[-10, 0, 10]
], {
name: 'angle',
needsRegularUpdate: true
//snapWidth: 1
});
//create slider for adjusting the angular speed
var sOmega = board.create('slider', [
[1, -7.5],
[6, -7.5],
[0, 0, 10]
], {
name: 'Omega',
needsRegularUpdate: true
//snapWidth: 1,
});
//fix parameters
const g = 9.81 //gravitational acceleration
const h0 = 5 //initial height of the water surface
//define radius from the y-axis for I3 and I4
const R34 = Math.sqrt(2);
// Function for parallel projection
var project = function(crd, cam) {
var d = -crd[2] / cam[2];
return [1, crd[0] + d * cam[0], crd[1] + d * cam[1]];
};
//function creates points for drawing conic sections
function PPoint(radius, sign, namep, fixval) {
this.R = radius;
this.S = sign;
this.Namep = namep;
this.Fixval = fixval;
this.pcoord = undefined; //Cartesian coordinates of the point, stored as a point
}
//method for drawing each Point
PPoint.prototype.draw = function(pp) {
board.create('point', [function() {
var K1 = sOmega.Value() * sOmega.Value() / g,
KK = 1 / 4 * sOmega.Value() * sOmega.Value() / g,
v = sRadius.Value() * Math.PI * 0.5 / 10.0,
c = [pp.S * pp.R * Math.sin(v), K1 / 2 * pp.R * pp.R - KK + h0, pp.S * pp.R * Math.cos(v)];
//store the dynamically assigned coordinates of the point for drawing the parabola
pp.pcoord = board.create('point', [function() {
return project(c, cam);
}], {
visible: false
}); //end storing pp.coord
return project(c, cam);
}], {
fixed: this.Fixval,
name: this.Namep,
visible: true
})
}
//create and draw points
var p_1 = new PPoint(0, -1, 'p_1', 'false');
var I_1 = new PPoint(r, 1, 'I_1', 'false');
var I_2 = new PPoint(r, -1, 'I_2', 'false');
var I_3 = new PPoint(R34, 1, 'I_3', 'false');
var I_4 = new PPoint(R34, -1, 'I_4', 'false');
p_1.draw(p_1)
I_1.draw(I_1)
I_2.draw(I_2)
I_3.draw(I_3)
I_4.draw(I_4)
//draw the rotating parabola
var prbl = board.create('conic', [I_1.pcoord, I_2.pcoord, I_3.pcoord, I_4.pcoord, p_1.pcoord], {
strokeColor: '#CA7291',
strokeWidth: 2,
trace :true
});
//debugger
这段代码有两个问题:
1) 在 PPoint.draw
中,引用两个 JSXGraph 点不起作用:在每次更新中都会创建一个新的 JSXGraph 点。这会使代码变慢,而且不会影响提供给圆锥曲线的初始点。我建议将 draw
更改为:
PPoint.prototype.draw = function(pp) {
pp.pcoord = board.create('point', [function() {
var K1 = sOmega.Value() * sOmega.Value() / g,
KK = 1 / 4 * sOmega.Value() * sOmega.Value() / g,
v = sRadius.Value() * Math.PI * 0.5 / 10.0,
c = [pp.S * pp.R * Math.sin(v),
K1 / 2 * pp.R * pp.R - KK + h0,
pp.S * pp.R * Math.cos(v)];
return project(c, cam);
}], {
fixed: this.Fixval,
name: this.Namep,
visible: true});
2) 第二个问题是 JSXGraph 无法通过五个点绘制退化二次曲线,并且如果二次曲线接近退化(一般抛物线存在数值问题),则精度会受到影响。此处的起始值 omega = 0
就是这种情况。
这是一个工作示例:https://jsfiddle.net/L2d4zt8q/