3

I have a graph in which users can create points and draw lines. These lines can be moved by the user. I also have added a fixed polygon (EFGH) around the lines. Now I need to find a way to allow users to click and pick the area that is formed by the lines and EFGH. I thought of generating a polygon for each of these areas and giving a fill color when clicked. But since these lines can be moved the polygons would have to be generated dynamically. I am not sure how to identify endpoints and create them. The requirement is to identify the area picked by the user and shade it and so if there is a simpler solution other than creating polygons, it is ok too. Although sample code would be helpful, I'd appreciate if someone can at least point me in a direction.

The image below shows an example with 2 lines(and 4 areas) although there could be more.

Jsxgraph requirement

Sample code can be seen below

let board = JXG.JSXGraph.initBoard('jxgbox', {boundingbox: [-13, 10, 10, -10], 
axis:true, keepAspectRatio:true});
var p1 = board.create('point', [0, 0]);
var p2 = board.create('point',  [1.0, 1.0]);
var p3 = board.create('point', [3, 0]);
var p4= board.create('point',  [3, 5],);

let l1 = board.create('line', [p1,p2],{dash:4});
let l2 = board.create('line', [p3,p4],{dash:4});


var p1x = board.create('point', [-5, 5],{fixed:true});
var p2x = board.create('point', [5, 5],{fixed:true});
var p3x = board.create('point', [5,-5],{fixed:true});
var p4x = board.create('point', [-5,-5],{fixed:true});

var pol = board.create('polygon', [p1x, p2x, p3x, p4x],{borders:{strokecolor:"green"},fillcolor:"white",highlightfillcolor:"white",fixed:true,});

The sample can be tried in this fiddle Jsxgraph fiddle

I have used JSXGraph
My requirement is similar to this

UPDATE 1:
I tried to use flood fill on JSXgraph canvas. But I was unable to select the correct point on the graph and also since the grid lines and axis were of different colors it prevented the fill so that didn't work either. This is what I have tried Flood fill Fiddle

1 Answers1

0

A start would be to use one line, add two inequality elements for this line and intersect these with the polygon. Additionally, the following example uses Jordan's point-in-polygon method to decide if a click is inside of one of the intersection paths.

const board = JXG.JSXGraph.initBoard('jxgbox', { 
    boundingbox: [-5, 5, 5, -5], axis:true
});

var isInside = function(pos, path) {
    var len = path.numberPoints, i, j,
        x = pos[0],
        y = pos[1],
        c = false;

    // Jordan's method, see https://en.wikipedia.org/wiki/Point_in_polygon
    for (i = 0, j = len - 1; i < len; j = i++) {
        if (( (path.points[i].usrCoords[2] > y) !== (path.points[j].usrCoords[2] > y) ) &&
            (x < (path.points[j].usrCoords[1] - path.points[i].usrCoords[1]) * (y - path.points[i].usrCoords[2]) /
                  (path.points[j].usrCoords[2] - path.points[i].usrCoords[2]) + path.points[i].usrCoords[1])) {
            c = !c;
        }
    }
    return c;
};

var pol = board.create('polygon', [[-3, -3], [3, -3], [3, 3], [-3, 3]]);
var li  = board.create('line', [[3, -4], [-2, 4]]);
var in1  = board.create('inequality', [li]);
var in2  = board.create('inequality', [li], {inverse: true, fillColor: 'pink'});
var isect1 = board.create('curve', [[], []], {fillColor: 'yellow', fillOpacity: 0.3});
    isect1.updateDataArray = function() {
        var a = JXG.Math.Clip.intersection(pol, in1, this.board);
        this.dataX = a[0];
        this.dataY = a[1];
    };
var isect2 = board.create('curve', [[], []], {fillColor: 'blue', fillOpacity: 0.3});
    isect2.updateDataArray = function() {
        var a = JXG.Math.Clip.intersection(pol, in2, this.board);
        this.dataX = a[0];
        this.dataY = a[1];
    };
    
board.on('down', function(evt) {
    var pos = this.getUsrCoordsOfMouse(evt),
        path, isIn,
        list = [isect1, isect2];

    for (path of list) {
        isIn = isInside(pos, path);
        if (isIn) {
            path.setAttribute({fillColor: 'gray'});
        }
    }
});

See it live at https://jsfiddle.net/e64qyLxt/1/.

Alfred Wassermann
  • 2,248
  • 1
  • 11
  • 10