简体   繁体   中英

In jsxgraph, why doesn't a parabola get drawn through five points on a same plane?

In a related question I was looking for a way to draw points in 3D space so that the points will move according to slider values. Now that is working, but the conic section (a parabola in this case) I am trying to draw through these points, is not drawn.

I thought that the constructor for the element "conic" might be picky about how the given points are defined, so I ended up adding as attributes "sub-objects" that are points that can be referred to when drawing the conic.

In my code below, the constructor function PPoint creates objects that have their respective attributes pcoord , which is a geometric object of type "point" created using the native jsxgraph constructor for points. pcoord is assigned when the method "draw" is called to the draw the points I_1-I-4 and p_1.

In the last lines of the code, the parabola should be drawn by referring to the pcoord s of objects I_1-I_4 and p_1, but for some reason the parabola is not drawn.

How could this be fixed? Link to jsfiddle . The code is executed without error notifications when debugging.

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

There are two issues with this code:

1) In PPoint.draw the reference two the JSXGraph point does not work: in each update an new JSXGraph point is created. This makes the code slow and - moreover - does not influence the initial points supplied to the conic section. I would propose to change draw to this:

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) The second problem is that JSXGraph fails to plot degenerated conics through five points and suffers in precision if the conic is close to be degenerated (there are numerical issues with general parabolas). This is the case here for the start value omega = 0 .

Here is a working example: https://jsfiddle.net/L2d4zt8q/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM