diff --git a/packages/doenetml-worker/src/components/dynamicalSystems/CobwebPolyline.js b/packages/doenetml-worker/src/components/dynamicalSystems/CobwebPolyline.js index 0325e6477..919292f01 100644 --- a/packages/doenetml-worker/src/components/dynamicalSystems/CobwebPolyline.js +++ b/packages/doenetml-worker/src/components/dynamicalSystems/CobwebPolyline.js @@ -129,7 +129,10 @@ export default class CobwebPolyline extends Polyline { let essentialInitialPoint = {}; for (let arrayKey of arrayKeys) { let varEnding = Number(arrayKey) + 1; - if (dependencyValuesByKey[arrayKey].initialPointAttr) { + if ( + dependencyValuesByKey[arrayKey].initialPointAttr + ?.stateValues["x" + varEnding] + ) { initialPoint[arrayKey] = dependencyValuesByKey[ arrayKey diff --git a/packages/doenetml/src/Viewer/renderers/cobwebPolyline.jsx b/packages/doenetml/src/Viewer/renderers/cobwebPolyline.jsx index 46cb45d2d..1053df7d4 100644 --- a/packages/doenetml/src/Viewer/renderers/cobwebPolyline.jsx +++ b/packages/doenetml/src/Viewer/renderers/cobwebPolyline.jsx @@ -79,20 +79,9 @@ export default React.memo(function CobwebPolyline(props) { diagonalAttributes, ); - let validCoords = true; - - for (let coords of SVs.numericalVertices) { - if (!Number.isFinite(coords[0])) { - validCoords = false; - } - if (!Number.isFinite(coords[1])) { - validCoords = false; - } - } - let jsxPolylineAttributes = { name: SVs.labelForGraph, - visible: !SVs.hidden && validCoords, + visible: !SVs.hidden, withLabel: SVs.labelForGraph !== "", fixed: true, layer: 10 * SVs.layer + LINE_LAYER_OFFSET, @@ -112,7 +101,7 @@ export default React.memo(function CobwebPolyline(props) { jsxPointAttributes.current = { fixed: !SVs.draggable || SVs.fixed, - visible: !SVs.hidden && validCoords && SVs.draggable, + visible: !SVs.hidden && SVs.draggable, withLabel: true, name: "A", layer: 10 * SVs.layer + VERTEX_LAYER_OFFSET, @@ -142,13 +131,13 @@ export default React.memo(function CobwebPolyline(props) { if (i === 0) { pointAttributes.name = `(${varName}_0,0)`; } else if (i % 2 === 1) { - pointAttributes.name = `(${varName}_${ + pointAttributes.name = `(${varName}_{${ (i - 1) / 2 - }, ${varName}_${(i + 1) / 2})`; + }}, ${varName}_{${(i + 1) / 2}})`; } else { - pointAttributes.name = `(${varName}_${i / 2}, ${varName}_${ + pointAttributes.name = `(${varName}_{${i / 2}}, ${varName}_{${ i / 2 - })`; + }})`; } if (i !== SVs.numPoints - 1) { pointAttributes.visible = false; @@ -299,17 +288,6 @@ export default React.memo(function CobwebPolyline(props) { curveJXG.current.needsUpdate = true; curveJXG.current.updateCurve(); - let validCoords = true; - - for (let coords of SVs.numericalVertices) { - if (!Number.isFinite(coords[0])) { - validCoords = false; - } - if (!Number.isFinite(coords[1])) { - validCoords = false; - } - } - let varName = SVs.variable.toString(); // add or delete points as required and change data array size @@ -322,13 +300,13 @@ export default React.memo(function CobwebPolyline(props) { if (i === 0) { pointAttributes.name = `(${varName}_0,0)`; } else if (i % 2 === 1) { - pointAttributes.name = `(${varName}_${ + pointAttributes.name = `(${varName}_{${ (i - 1) / 2 - }, ${varName}_${(i + 1) / 2})`; + }}, ${varName}_{${(i + 1) / 2}})`; } else { - pointAttributes.name = `(${varName}_${ + pointAttributes.name = `(${varName}_{${ i / 2 - }, ${varName}_${i / 2})`; + }}, ${varName}_{${i / 2}})`; } if (i !== SVs.numPoints - 1) { pointAttributes.visible = false; @@ -386,33 +364,21 @@ export default React.memo(function CobwebPolyline(props) { let visible = !SVs.hidden; - if (validCoords) { - polylineJXG.current.visProp["visible"] = visible; - polylineJXG.current.visPropCalc["visible"] = visible; - // polylineJXG.current.setAttribute({visible: visible}) + polylineJXG.current.visProp["visible"] = visible; + polylineJXG.current.visPropCalc["visible"] = visible; + // polylineJXG.current.setAttribute({visible: visible}) - for (let i = 0; i < SVs.numPoints - 1; i++) { - pointsJXG.current[i].visProp["visible"] = false; - pointsJXG.current[i].visPropCalc["visible"] = false; - } - if (SVs.numPoints > 0) { - if (SVs.draggable) { - pointsJXG.current[SVs.numPoints - 1].visProp[ - "visible" - ] = visible; - pointsJXG.current[SVs.numPoints - 1].visPropCalc[ - "visible" - ] = visible; - } - } - } else { - polylineJXG.current.visProp["visible"] = false; - polylineJXG.current.visPropCalc["visible"] = false; - // polylineJXG.current.setAttribute({visible: false}) - - for (let i = 0; i < SVs.numPoints; i++) { - pointsJXG.current[i].visProp["visible"] = false; - pointsJXG.current[i].visPropCalc["visible"] = false; + for (let i = 0; i < SVs.numPoints - 1; i++) { + pointsJXG.current[i].visProp["visible"] = false; + pointsJXG.current[i].visPropCalc["visible"] = false; + } + if (SVs.numPoints > 0) { + if (SVs.draggable) { + pointsJXG.current[SVs.numPoints - 1].visProp["visible"] = + visible; + pointsJXG.current[SVs.numPoints - 1].visPropCalc[ + "visible" + ] = visible; } } diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js index 9fc3a9d67..e7d4c3bf6 100644 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +++ b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js @@ -2737,4 +2737,75 @@ describe("CobwebPolyline Tag Tests", function () { cy.get(cesc2("#/cobwebTutorial/next_button")).should("be.disabled"); cy.get(cesc2("#/ca")).should("have.text", "1"); }); + + it("handle bad initial point, lock to solution", () => { + cy.window().then(async (win) => { + win.postMessage( + { + doenetML: ` + + x^2 + + +

Initial point:

+ + + + +

Vertices: $cobweb.vertices

+ + + `, + }, + "*", + ); + }); + + cy.get(cesc2("#/_p1")).should("have.text", "Initial point: "); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(0) + .should("have.text", "(_,0)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(3) + .should("have.text", "(NaN,NaN)"); + + cy.get(cesc2("#/x0") + " textarea").type("0.9{enter}", { force: true }); + + cy.get(cesc2("#/_p2") + " .mjx-mrow").should("contain.text", "(0.9,0)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(0) + .should("have.text", "(0.9,0)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(2) + .should("have.text", "(0.9,0.81)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(100) + .should("have.text", "(0,0)"); + + cy.get(cesc2("#/x0") + " textarea").type( + "{end}{backspace}{backspace}{backspace}(1.1,3){enter}", + { + force: true, + }, + ); + + cy.get(cesc2("#/_p2") + " .mjx-mrow").should("contain.text", "(1.1,3)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(0) + .should("have.text", "(1.1,3)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(2) + .should("have.text", "(1.1,1.21)"); + + cy.get(cesc2("#/_p2") + " .mjx-mrow") + .eq(100) + .should("have.text", "(∞,∞)"); + }); });