Filling the space between 3 bezier curves

27 views
Skip to first unread message

Cyrille Piatecki

unread,
Sep 16, 2024, 6:07:26 AM9/16/24
to JSXGraph
First sory not to join a jsfiddle, but there are some problems when I try to compose a demonstration.

I have 3 curves and I would like to color the space they delimit but my tries fail. Here follow the last one

<div id="box1" class="jxgbox" style="width:430px; height:380px;"></div>
<script type="text/javascript">
JXG.Options.text.useMathJax = true;

var board = JXG.JSXGraph.initBoard("box1", {pan: {enabled:false},boundingbox: [0,30, 25,-4],
withLines:true,
keepaspectratio: true,
axis:false,
defaultAxes: {
    x: { ticks: {visible: false},withLabel: true,name: '$Y^d_t$',label: {
                position: 'rt',
                offset: [-5, 15],
                anchorX: 'right'
            } },
    y: { ticks: {visible: false},withLabel: true,name: '$C_t$', label: {
                position: 'rt',
                offset: [-20, -2],
                anchorY: 'top'
            } }
  },
showNavigation:false,showCopyright:false});
board.renderer.container.style.backgroundColor='white';//'#C5ADC5';
var ax = board.create('axis', [[-1, 0], [10, 0]],{ticks:{visible:false},majorHeight:4,withLabel:true,label:{name:"$x$",position:'rt',offset:[-20,10]},strokeWidth:1.5,});
var au = board.create('axis', [[0, -1], [0, 10]],{ticks:{visible:false},strokeWidth:1.5});
var ay = board.create('axis', [[-2, -1.75], [20,17]],{ticks:{visible:false},strokeWidth:1.5});

var p = [];
  p.push(board.create('point',  [0,0],{name:''}));
  p.push(board.create('point',  [11.04,20.92],{name:''}));
  p.push(board.create('point',  [1.91,24.32],{name:''}));
  p.push(board.create('point',  [25.42,22.46],{name:''}));
 
var c0 = board.create('curve', JXG.Math.Numerics.bezier(p), {strokecolor:'blue', strokeOpacity:0.6, strokeWidth:5});

var s = [];
  s.push(board.create('point',  [14.89,10.33],{name:'A'}));
  s.push(board.create('point',  [12.75,16.15],{name:'B'}));
  s.push(board.create('point',  [24.13,14.77],{name:'C'}));
  s.push(board.create('point',  [25.42,22.46],{name:'E'}));

var c1 = board.create('curve', JXG.Math.Numerics.bezier(s), {strokecolor:'blue', strokeOpacity:0.6, strokeWidth:5});

var q = [];
  q.push(board.create('point',  [0,0],{name:''}));
  q.push(board.create('point',  [7.64,1.46],{name:''}));
  q.push(board.create('point',  [7.31,10.83],{name:''}));
  q.push(board.create('point',  [14.89,10.33],{name:''}));
 
var c2 = board.create('curve', JXG.Math.Numerics.bezier(q), {strokecolor:'blue', strokeOpacity:0.6, strokeWidth:5});




var clip_path = board.create('curveintersection', [c0, c1, c2], {
    strokeWidth: 3,
    fillColor: 'yellow',
    fillOpacity: 0.3
});

Wigand Rathmann

unread,
Sep 16, 2024, 12:27:46 PM9/16/24
to JSXGraph
Dear Cyrille,
I think the way you have in mind will not work without a workaround:
To get a curveintersection of two curves, you will need at least one closed curve. (https://jsxgraph.uni-bayreuth.de/docs/symbols/CurveIntersection.html )
Furthermore curveIntersection takes only two objects. 
Regards,
Wigand

Cyrille Piatecki

unread,
Sep 17, 2024, 8:53:11 AM9/17/24
to JSXGraph
Dear Wigand,

it's exactly what I was observing. This is a lack. The only way to achieve what I want (which after all, is standard) , is to finely use a polygon to fill the surface. Believe me it's boring.

Alfred Wassermann

unread,
Sep 17, 2024, 9:31:12 AM9/17/24
to JSXGraph
Dear Cyrille and Wigand,
there is a way to achieve the curve filling, albeit it is a bit hacky and requires some care when creating the (original) curves.
My suggestion is to create a new curve and use its updateDataArray method to concatenate all points from the input curves c0, c1, and c2. This can be done like this:

        var clip_path = board.create('curve', [[], []], {

            strokeWidth: 3,
            fillColor: 'yellow',
            fillOpacity: 0.3
        });

        clip_path.updateDataArray = function() {
            var i, j, le,
                curves = [c0, c1, c2];

            this.dataX = [];
            this.dataY = [];

            for (j = 0; j < curves.length; j++) {
                for (i = 0; i < curves[j].numberPoints; i++) {
                    this.dataX.push(curves[j].points[i].usrCoords[1]);
                    this.dataY.push(curves[j].points[i].usrCoords[2]);
                }
            }
        };
        board.update();

However, the orientation of the input curves has to be adapted such that we have a closed path. In your case I reversed c1 and c2:

        var s = [];
        s.push(board.create('point', [25.42, 22.46], { name: 'E' }));
        s.push(board.create('point', [24.13, 14.77], { name: 'C' }));
        s.push(board.create('point', [12.75, 16.15], { name: 'B' }));
        s.push(board.create('point', [14.89, 10.33], { name: 'A' }));

        var c1 = board.create('curve', JXG.Math.Numerics.bezier(s), { strokecolor: 'blue', strokeOpacity: 0.6, strokeWidth: 1 });

        var q = [];
        q.push(board.create('point', [14.89, 10.33], { name: '' }));
        q.push(board.create('point', [7.31, 10.83], { name: '' }));
        q.push(board.create('point', [7.64, 1.46], { name: '' }));
        q.push(board.create('point', [0, 0], { name: '' }));

        var c2 = board.create('curve', JXG.Math.Numerics.bezier(q), { strokecolor: 'blue', strokeOpacity: 0.6, strokeWidth: 1 });

See it live at https://jsfiddle.net/dyu8rh5k/.
By the way, how to you get this beautiful syntax highlighting in Google Groups?

Best wishes,
Alfred
Reply all
Reply to author
Forward
0 new messages