@doenet/v06-to-v07 0.7.21-dev.346 → 0.7.21-dev.347

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40963,7 +40963,7 @@ async function cidFromArrayBuffer(data) {
40963
40963
  await crypto.subtle.digest("SHA-256", new Uint8Array());
40964
40964
  digest = (data2) => crypto.subtle.digest("SHA-256", data2);
40965
40965
  } catch (e22) {
40966
- const sha256 = (await import("./sha256-C0vj3HDn-A0bbFFmK-Drhbnw70.js").then((n2) => n2.s)).default;
40966
+ const sha256 = (await import("./sha256-C0vj3HDn-DgMb2jlU-CPBnemG6.js").then((n2) => n2.s)).default;
40967
40967
  digest = (data2) => sha256(data2, {
40968
40968
  asBytes: true
40969
40969
  });
@@ -120332,6 +120332,136 @@ class Coords extends MathComponent {
120332
120332
  // }
120333
120333
  // }
120334
120334
  }
120335
+ function buildIgnoredPhrase(ignored) {
120336
+ if (ignored.length === 1) {
120337
+ return `${ignored[0]} is`;
120338
+ } else if (ignored.length === 2) {
120339
+ return `${ignored[0]} and ${ignored[1]} are`;
120340
+ } else {
120341
+ return `${ignored.slice(0, -1).join(", ")}, and ${ignored.slice(-1)} are`;
120342
+ }
120343
+ }
120344
+ function directionFromSlope(slope) {
120345
+ if (slope === Infinity || slope === -Infinity) {
120346
+ return [0, Math.sign(slope)];
120347
+ }
120348
+ if (!Number.isFinite(slope)) {
120349
+ return null;
120350
+ }
120351
+ let theta = Math.atan(slope);
120352
+ return [Math.cos(theta), Math.sin(theta)];
120353
+ }
120354
+ function getNumericValue(mathOrNumber) {
120355
+ return mathOrNumber instanceof Context.class ? mathOrNumber.evaluate_to_constant() : Number(mathOrNumber);
120356
+ }
120357
+ function getNumericEndpointPair(desiredUnconstrainedEndpoints, currentEndpoints, numDimensions = 2, pointInds = [0, 1]) {
120358
+ return pointInds.map(
120359
+ (pointInd) => Array.from({ length: numDimensions }, (_2, dim) => {
120360
+ let key = pointInd + "," + dim;
120361
+ if (key in desiredUnconstrainedEndpoints) {
120362
+ return getNumericValue(desiredUnconstrainedEndpoints[key]);
120363
+ }
120364
+ return currentEndpoints[pointInd][dim].evaluate_to_constant();
120365
+ })
120366
+ );
120367
+ }
120368
+ function getSlopeAndSignedLength(endpoint1, endpoint2, fallbackSlope) {
120369
+ const dx = endpoint2[0] - endpoint1[0];
120370
+ const dy = endpoint2[1] - endpoint1[1];
120371
+ if (dx === 0 && dy === 0) {
120372
+ return {
120373
+ slope: fallbackSlope,
120374
+ signedLength: 0
120375
+ };
120376
+ }
120377
+ if (dx === 0) {
120378
+ return {
120379
+ slope: dy > 0 ? Infinity : -Infinity,
120380
+ // For vertical segments, canonicalize interactions so slope encodes
120381
+ // up vs down and the defining length stays non-negative.
120382
+ signedLength: Math.abs(dy)
120383
+ };
120384
+ }
120385
+ return {
120386
+ slope: dy / dx,
120387
+ signedLength: Math.hypot(dx, dy) * Math.sign(dx)
120388
+ };
120389
+ }
120390
+ function getDirectionComponent(dim, dirX, dirY) {
120391
+ let dimNumber = Number(dim);
120392
+ if (dimNumber === 0) {
120393
+ return dirX;
120394
+ }
120395
+ if (dimNumber === 1) {
120396
+ return dirY;
120397
+ }
120398
+ return 0;
120399
+ }
120400
+ function getConfiguredSlope(globalDependencyValues) {
120401
+ return globalDependencyValues.slopeAttr !== null ? globalDependencyValues.slopeAttr.stateValues.value : globalDependencyValues.essentialSlope;
120402
+ }
120403
+ function getConfiguredSignedLength(globalDependencyValues) {
120404
+ return globalDependencyValues.lengthAttr !== null ? globalDependencyValues.lengthAttr.stateValues.value : globalDependencyValues.essentialSignedLength;
120405
+ }
120406
+ function addSlopeAndLengthInstructions({
120407
+ instructions,
120408
+ globalDependencyValues,
120409
+ endpoint1,
120410
+ endpoint2
120411
+ }) {
120412
+ const fallbackSlope = getConfiguredSlope(globalDependencyValues);
120413
+ const { slope, signedLength } = getSlopeAndSignedLength(
120414
+ endpoint1,
120415
+ endpoint2,
120416
+ fallbackSlope
120417
+ );
120418
+ if (globalDependencyValues.slopeAttr !== null) {
120419
+ instructions.push({
120420
+ setDependency: "slopeAttr",
120421
+ desiredValue: slope,
120422
+ variableIndex: 0
120423
+ });
120424
+ } else {
120425
+ instructions.push({
120426
+ setDependency: "essentialSlope",
120427
+ desiredValue: slope
120428
+ });
120429
+ }
120430
+ if (globalDependencyValues.lengthAttr !== null) {
120431
+ instructions.push({
120432
+ setDependency: "lengthAttr",
120433
+ desiredValue: signedLength,
120434
+ variableIndex: 0
120435
+ });
120436
+ } else {
120437
+ instructions.push({
120438
+ setDependency: "essentialSignedLength",
120439
+ desiredValue: signedLength
120440
+ });
120441
+ }
120442
+ }
120443
+ function addMidpointInstructions({
120444
+ instructions,
120445
+ dependencyNamesByKey,
120446
+ midpointCoords
120447
+ }) {
120448
+ for (let dim = 0; dim < midpointCoords.length; dim++) {
120449
+ const midpointDependencyName = dependencyNamesByKey["0," + dim]?.midpointCoord;
120450
+ if (midpointDependencyName !== void 0) {
120451
+ instructions.push({
120452
+ setDependency: midpointDependencyName,
120453
+ desiredValue: Context.fromAst(midpointCoords[dim]),
120454
+ variableIndex: 0
120455
+ });
120456
+ }
120457
+ }
120458
+ }
120459
+ function mergePointCoords(pointCoords, currentPoint, numDimensions) {
120460
+ return Array.from(
120461
+ { length: numDimensions },
120462
+ (_2, dim) => pointCoords[dim] !== void 0 ? pointCoords[dim] : currentPoint[dim]
120463
+ );
120464
+ }
120335
120465
  class LineSegment extends GraphicalComponent {
120336
120466
  constructor(args) {
120337
120467
  super(args);
@@ -120365,6 +120495,25 @@ class LineSegment extends GraphicalComponent {
120365
120495
  createComponentOfType: "pointList",
120366
120496
  description: "The two endpoints of the line segment."
120367
120497
  };
120498
+ attributes.midpoint = {
120499
+ createComponentOfType: "point",
120500
+ description: "A reference point on the line segment, located at its midpoint by default. Used with slope/length/midpointOffset to position the segment. When midpointOffset is nonzero, this point is offset from the segment's actual midpoint (given by the midpoint property)."
120501
+ };
120502
+ attributes.slope = {
120503
+ createComponentOfType: "number",
120504
+ description: "The slope of the line segment in the x-y plane."
120505
+ };
120506
+ attributes.length = {
120507
+ createComponentOfType: "number",
120508
+ description: "The signed defining length used with the slope/midpoint parameterization. Negative values flip the relative position of the endpoints."
120509
+ };
120510
+ attributes.midpointOffset = {
120511
+ createComponentOfType: "number",
120512
+ createStateVariable: "midpointOffset",
120513
+ defaultValue: 0,
120514
+ clamp: [-1, 1],
120515
+ description: "Where the point given by the midpoint attribute sits along the segment (requires midpoint to be set): -1=first endpoint, 0=midpoint, 1=second endpoint. Clamped to [-1, 1]."
120516
+ };
120368
120517
  attributes.addControls = {
120369
120518
  description: "Whether to render interactive control handles.",
120370
120519
  createComponentOfType: "text",
@@ -120509,18 +120658,218 @@ class LineSegment extends GraphicalComponent {
120509
120658
  dependencyType: "attributeComponent",
120510
120659
  attributeName: "endpoints",
120511
120660
  variableNames: ["numDimensions"]
120661
+ },
120662
+ midpointAttr: {
120663
+ dependencyType: "attributeComponent",
120664
+ attributeName: "midpoint",
120665
+ variableNames: ["numDimensions"]
120512
120666
  }
120513
120667
  }),
120514
120668
  definition: function({ dependencyValues }) {
120515
- if (dependencyValues.endpointsAttr !== null) {
120516
- let numDimensions = dependencyValues.endpointsAttr.stateValues.numDimensions;
120517
- return {
120518
- setValue: { numDimensions: Math.max(numDimensions, 2) },
120519
- checkForActualChange: { numDimensions: true }
120520
- };
120521
- } else {
120522
- return { setValue: { numDimensions: 2 } };
120669
+ const endpointsDimensions = dependencyValues.endpointsAttr?.stateValues.numDimensions ?? 0;
120670
+ const midpointDimensions = dependencyValues.midpointAttr?.stateValues.numDimensions ?? 0;
120671
+ return {
120672
+ setValue: {
120673
+ numDimensions: Math.max(
120674
+ endpointsDimensions,
120675
+ midpointDimensions,
120676
+ 2
120677
+ )
120678
+ },
120679
+ checkForActualChange: { numDimensions: true }
120680
+ };
120681
+ }
120682
+ };
120683
+ stateVariableDefinitions.numEndpointsSpecified = {
120684
+ returnDependencies: () => ({
120685
+ endpointsAttr: {
120686
+ dependencyType: "attributeComponent",
120687
+ attributeName: "endpoints",
120688
+ variableNames: ["numPoints"]
120523
120689
  }
120690
+ }),
120691
+ definition({ dependencyValues }) {
120692
+ if (dependencyValues.endpointsAttr === null) {
120693
+ return { setValue: { numEndpointsSpecified: 0 } };
120694
+ }
120695
+ return {
120696
+ setValue: {
120697
+ numEndpointsSpecified: Math.min(
120698
+ dependencyValues.endpointsAttr.stateValues.numPoints,
120699
+ 2
120700
+ )
120701
+ }
120702
+ };
120703
+ }
120704
+ };
120705
+ stateVariableDefinitions.midpointSpecified = {
120706
+ returnDependencies: () => ({
120707
+ midpointAttr: {
120708
+ dependencyType: "attributeComponent",
120709
+ attributeName: "midpoint"
120710
+ }
120711
+ }),
120712
+ definition({ dependencyValues }) {
120713
+ return {
120714
+ setValue: {
120715
+ midpointSpecified: dependencyValues.midpointAttr !== null
120716
+ }
120717
+ };
120718
+ }
120719
+ };
120720
+ stateVariableDefinitions.basedOnSlopeOrMidpoint = {
120721
+ stateVariablesDeterminingDependencies: [],
120722
+ returnDependencies: () => ({
120723
+ slopeAttr: {
120724
+ dependencyType: "attributeComponent",
120725
+ attributeName: "slope"
120726
+ },
120727
+ lengthAttr: {
120728
+ dependencyType: "attributeComponent",
120729
+ attributeName: "length"
120730
+ },
120731
+ midpointSpecified: {
120732
+ dependencyType: "stateVariable",
120733
+ variableName: "midpointSpecified"
120734
+ },
120735
+ numEndpointsSpecified: {
120736
+ dependencyType: "stateVariable",
120737
+ variableName: "numEndpointsSpecified"
120738
+ },
120739
+ midpointOffset: {
120740
+ dependencyType: "stateVariable",
120741
+ variableName: "midpointOffset"
120742
+ }
120743
+ }),
120744
+ definition({ dependencyValues, usedDefault }) {
120745
+ const anyPositioningAttr = dependencyValues.slopeAttr !== null || dependencyValues.lengthAttr !== null || dependencyValues.midpointSpecified;
120746
+ const basedOnSlopeOrMidpoint = anyPositioningAttr && dependencyValues.numEndpointsSpecified < 2;
120747
+ const result2 = {
120748
+ setValue: {
120749
+ basedOnSlopeOrMidpoint
120750
+ }
120751
+ };
120752
+ if (anyPositioningAttr && !basedOnSlopeOrMidpoint) {
120753
+ const ignored = [];
120754
+ if (dependencyValues.slopeAttr !== null) {
120755
+ ignored.push("slope");
120756
+ }
120757
+ if (dependencyValues.lengthAttr !== null) {
120758
+ ignored.push("length");
120759
+ }
120760
+ if (dependencyValues.midpointSpecified) {
120761
+ ignored.push("midpoint");
120762
+ }
120763
+ if (!usedDefault.midpointOffset) {
120764
+ ignored.push("midpointOffset");
120765
+ }
120766
+ result2.sendDiagnostics = [
120767
+ {
120768
+ type: "info",
120769
+ message: `${buildIgnoredPhrase(ignored)} ignored when two endpoints are specified`
120770
+ }
120771
+ ];
120772
+ } else if (!basedOnSlopeOrMidpoint && !usedDefault.midpointOffset) {
120773
+ result2.sendDiagnostics = [
120774
+ {
120775
+ type: "info",
120776
+ message: "midpointOffset has no effect without a midpoint"
120777
+ }
120778
+ ];
120779
+ }
120780
+ return result2;
120781
+ }
120782
+ };
120783
+ stateVariableDefinitions.essentialSlope = {
120784
+ defaultValue: 0,
120785
+ hasEssential: true,
120786
+ returnDependencies: () => ({}),
120787
+ definition: () => ({
120788
+ useEssentialOrDefaultValue: { essentialSlope: true }
120789
+ }),
120790
+ inverseDefinition({ desiredStateVariableValues }) {
120791
+ return {
120792
+ success: true,
120793
+ instructions: [
120794
+ {
120795
+ setEssentialValue: "essentialSlope",
120796
+ value: desiredStateVariableValues.essentialSlope
120797
+ }
120798
+ ]
120799
+ };
120800
+ }
120801
+ };
120802
+ stateVariableDefinitions.essentialSignedLength = {
120803
+ defaultValue: 1,
120804
+ hasEssential: true,
120805
+ returnDependencies: () => ({}),
120806
+ definition: () => ({
120807
+ useEssentialOrDefaultValue: { essentialSignedLength: true }
120808
+ }),
120809
+ inverseDefinition({ desiredStateVariableValues }) {
120810
+ return {
120811
+ success: true,
120812
+ instructions: [
120813
+ {
120814
+ setEssentialValue: "essentialSignedLength",
120815
+ value: desiredStateVariableValues.essentialSignedLength
120816
+ }
120817
+ ]
120818
+ };
120819
+ }
120820
+ };
120821
+ stateVariableDefinitions.essentialEp1 = {
120822
+ isArray: true,
120823
+ numDimensions: 1,
120824
+ isLocation: true,
120825
+ hasEssential: true,
120826
+ set: convertValueToMathExpression,
120827
+ defaultValueByArrayKey: () => Context.fromAst(0),
120828
+ entryPrefixes: ["essentialEp1X"],
120829
+ getArrayKeysFromVarName({
120830
+ arrayEntryPrefix,
120831
+ varEnding,
120832
+ arraySize: arraySize2
120833
+ }) {
120834
+ let ind = Number(varEnding) - 1;
120835
+ if (!Number.isInteger(ind) || ind < 0) {
120836
+ return [];
120837
+ }
120838
+ if (arraySize2) {
120839
+ return ind < arraySize2[0] ? [String(ind)] : [];
120840
+ }
120841
+ return [String(ind)];
120842
+ },
120843
+ returnArraySizeDependencies: () => ({
120844
+ numDimensions: {
120845
+ dependencyType: "stateVariable",
120846
+ variableName: "numDimensions"
120847
+ }
120848
+ }),
120849
+ returnArraySize({ dependencyValues }) {
120850
+ return [dependencyValues.numDimensions];
120851
+ },
120852
+ returnArrayDependenciesByKey: () => ({}),
120853
+ arrayDefinitionByKey({ arrayKeys }) {
120854
+ let essentialEp1 = {};
120855
+ for (let arrayKey of arrayKeys) {
120856
+ essentialEp1[arrayKey] = true;
120857
+ }
120858
+ return { useEssentialOrDefaultValue: { essentialEp1 } };
120859
+ },
120860
+ inverseArrayDefinitionByKey({ desiredStateVariableValues }) {
120861
+ let instructions = [];
120862
+ for (let arrayKey in desiredStateVariableValues.essentialEp1) {
120863
+ instructions.push({
120864
+ setEssentialValue: "essentialEp1",
120865
+ value: {
120866
+ [arrayKey]: convertValueToMathExpression(
120867
+ desiredStateVariableValues.essentialEp1[arrayKey]
120868
+ )
120869
+ }
120870
+ });
120871
+ }
120872
+ return { success: true, instructions };
120524
120873
  }
120525
120874
  };
120526
120875
  stateVariableDefinitions.unconstrainedEndpoints = {
@@ -120595,75 +120944,485 @@ class LineSegment extends GraphicalComponent {
120595
120944
  returnArraySize({ dependencyValues }) {
120596
120945
  return [2, dependencyValues.numDimensions];
120597
120946
  },
120598
- returnArrayDependenciesByKey({ arrayKeys }) {
120599
- let dependenciesByKey = {};
120600
- for (let arrayKey of arrayKeys) {
120601
- let [pointInd, dim] = arrayKey.split(",");
120602
- let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
120603
- dependenciesByKey[arrayKey] = {
120604
- endpointsAttr: {
120605
- dependencyType: "attributeComponent",
120606
- attributeName: "endpoints",
120607
- variableNames: ["pointX" + varEnding]
120947
+ stateVariablesDeterminingDependencies: [
120948
+ "basedOnSlopeOrMidpoint",
120949
+ "numEndpointsSpecified",
120950
+ "midpointSpecified"
120951
+ ],
120952
+ returnArrayDependenciesByKey({ stateValues, arrayKeys }) {
120953
+ if (!stateValues.basedOnSlopeOrMidpoint) {
120954
+ let dependenciesByKey2 = {};
120955
+ for (let arrayKey of arrayKeys) {
120956
+ let [pointInd, dim] = arrayKey.split(",");
120957
+ let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
120958
+ dependenciesByKey2[arrayKey] = {
120959
+ endpointsAttr: {
120960
+ dependencyType: "attributeComponent",
120961
+ attributeName: "endpoints",
120962
+ variableNames: ["pointX" + varEnding]
120963
+ }
120964
+ };
120965
+ }
120966
+ return { dependenciesByKey: dependenciesByKey2 };
120967
+ }
120968
+ let globalDependencies = {
120969
+ basedOnSlopeOrMidpoint: {
120970
+ dependencyType: "stateVariable",
120971
+ variableName: "basedOnSlopeOrMidpoint"
120972
+ },
120973
+ numEndpointsSpecified: {
120974
+ dependencyType: "stateVariable",
120975
+ variableName: "numEndpointsSpecified"
120976
+ },
120977
+ midpointSpecified: {
120978
+ dependencyType: "stateVariable",
120979
+ variableName: "midpointSpecified"
120980
+ },
120981
+ numDimensions: {
120982
+ dependencyType: "stateVariable",
120983
+ variableName: "numDimensions"
120984
+ },
120985
+ slopeAttr: {
120986
+ dependencyType: "attributeComponent",
120987
+ attributeName: "slope",
120988
+ variableNames: ["value"]
120989
+ },
120990
+ lengthAttr: {
120991
+ dependencyType: "attributeComponent",
120992
+ attributeName: "length",
120993
+ variableNames: ["value"]
120994
+ },
120995
+ midpointOffset: {
120996
+ dependencyType: "stateVariable",
120997
+ variableName: "midpointOffset"
120998
+ },
120999
+ essentialSlope: {
121000
+ dependencyType: "stateVariable",
121001
+ variableName: "essentialSlope"
121002
+ },
121003
+ essentialSignedLength: {
121004
+ dependencyType: "stateVariable",
121005
+ variableName: "essentialSignedLength"
121006
+ }
121007
+ };
121008
+ if (stateValues.numEndpointsSpecified === 1) {
121009
+ globalDependencies.ep1FromAttr = {
121010
+ dependencyType: "attributeComponent",
121011
+ attributeName: "endpoints",
121012
+ variableNames: []
121013
+ };
121014
+ let dependenciesByKey2 = {};
121015
+ for (let arrayKey of arrayKeys) {
121016
+ let [pointInd, dim] = arrayKey.split(",");
121017
+ let varEnding = "1_" + (Number(dim) + 1);
121018
+ dependenciesByKey2[arrayKey] = {
121019
+ ep1Coord: {
121020
+ dependencyType: "attributeComponent",
121021
+ attributeName: "endpoints",
121022
+ variableNames: ["pointX" + varEnding]
121023
+ }
121024
+ };
121025
+ }
121026
+ if (stateValues.midpointSpecified) {
121027
+ for (let arrayKey of arrayKeys) {
121028
+ let dim = Number(arrayKey.split(",")[1]);
121029
+ dependenciesByKey2[arrayKey].midpointCoord = {
121030
+ dependencyType: "attributeComponent",
121031
+ attributeName: "midpoint",
121032
+ variableNames: ["x" + (dim + 1)]
121033
+ };
120608
121034
  }
121035
+ }
121036
+ return { globalDependencies, dependenciesByKey: dependenciesByKey2 };
121037
+ }
121038
+ let dependenciesByKey = {};
121039
+ if (stateValues.midpointSpecified) {
121040
+ for (let arrayKey of arrayKeys) {
121041
+ let dim = Number(arrayKey.split(",")[1]);
121042
+ dependenciesByKey[arrayKey] = {
121043
+ midpointCoord: {
121044
+ dependencyType: "attributeComponent",
121045
+ attributeName: "midpoint",
121046
+ variableNames: ["x" + (dim + 1)]
121047
+ }
121048
+ };
121049
+ }
121050
+ } else {
121051
+ globalDependencies.essentialEp1 = {
121052
+ dependencyType: "stateVariable",
121053
+ variableName: "essentialEp1"
120609
121054
  };
121055
+ for (let arrayKey of arrayKeys) {
121056
+ dependenciesByKey[arrayKey] = {};
121057
+ }
121058
+ return { globalDependencies, dependenciesByKey };
120610
121059
  }
120611
- return { dependenciesByKey };
121060
+ return { globalDependencies, dependenciesByKey };
120612
121061
  },
120613
- arrayDefinitionByKey({ dependencyValuesByKey, arrayKeys }) {
121062
+ arrayDefinitionByKey({
121063
+ globalDependencyValues,
121064
+ globalUsedDefault,
121065
+ dependencyValuesByKey,
121066
+ arrayKeys
121067
+ }) {
121068
+ if (!globalDependencyValues?.basedOnSlopeOrMidpoint) {
121069
+ let unconstrainedEndpoints2 = {};
121070
+ let essentialUnconstrainedEndpoints = {};
121071
+ for (let arrayKey of arrayKeys) {
121072
+ let [pointInd, dim] = arrayKey.split(",");
121073
+ let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
121074
+ if (dependencyValuesByKey[arrayKey].endpointsAttr !== null && dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding]) {
121075
+ unconstrainedEndpoints2[arrayKey] = dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding];
121076
+ } else {
121077
+ essentialUnconstrainedEndpoints[arrayKey] = true;
121078
+ }
121079
+ }
121080
+ let result22 = {};
121081
+ if (Object.keys(unconstrainedEndpoints2).length > 0) {
121082
+ result22.setValue = { unconstrainedEndpoints: unconstrainedEndpoints2 };
121083
+ }
121084
+ if (Object.keys(essentialUnconstrainedEndpoints).length > 0) {
121085
+ result22.useEssentialOrDefaultValue = {
121086
+ unconstrainedEndpoints: essentialUnconstrainedEndpoints
121087
+ };
121088
+ }
121089
+ return result22;
121090
+ }
121091
+ const g2 = globalDependencyValues;
121092
+ const gUsedDefault = globalUsedDefault;
121093
+ let sendDiagnostics = [];
121094
+ if (g2.numEndpointsSpecified === 1 && g2.midpointSpecified) {
121095
+ if (g2.slopeAttr !== null || g2.lengthAttr !== null) {
121096
+ const ignored = [];
121097
+ if (g2.slopeAttr !== null) {
121098
+ ignored.push("slope");
121099
+ }
121100
+ if (g2.lengthAttr !== null) {
121101
+ ignored.push("length");
121102
+ }
121103
+ sendDiagnostics.push({
121104
+ type: "info",
121105
+ message: `${buildIgnoredPhrase(ignored)} ignored when an endpoint and a midpoint are both specified`
121106
+ });
121107
+ }
121108
+ } else if (!g2.midpointSpecified && !gUsedDefault.midpointOffset) {
121109
+ sendDiagnostics.push({
121110
+ type: "info",
121111
+ message: "midpointOffset has no effect without a midpoint"
121112
+ });
121113
+ }
120614
121114
  let unconstrainedEndpoints = {};
120615
- let essentialUnconstrainedEndpoints = {};
120616
- for (let arrayKey of arrayKeys) {
120617
- let [pointInd, dim] = arrayKey.split(",");
120618
- let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
120619
- if (dependencyValuesByKey[arrayKey].endpointsAttr !== null && dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding]) {
120620
- unconstrainedEndpoints[arrayKey] = dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding];
121115
+ if (g2.numEndpointsSpecified === 1 && g2.midpointSpecified) {
121116
+ const tT = (1 + g2.midpointOffset) / 2;
121117
+ for (let arrayKey of arrayKeys) {
121118
+ let [pointInd, dim] = arrayKey.split(",");
121119
+ let varEnding = "1_" + (Number(dim) + 1);
121120
+ let ep1Coord = dependencyValuesByKey[arrayKey].ep1Coord?.stateValues["pointX" + varEnding];
121121
+ if (pointInd === "0") {
121122
+ unconstrainedEndpoints[arrayKey] = ep1Coord ?? Context.fromAst("_");
121123
+ continue;
121124
+ }
121125
+ let midpointVal = dependencyValuesByKey[arrayKey].midpointCoord?.stateValues["x" + (Number(dim) + 1)];
121126
+ if (tT === 0 || !ep1Coord || !midpointVal) {
121127
+ unconstrainedEndpoints[arrayKey] = Context.fromAst("_");
121128
+ continue;
121129
+ }
121130
+ let invT = 1 / tT;
121131
+ unconstrainedEndpoints[arrayKey] = Context.fromAst([
121132
+ "+",
121133
+ ["*", 1 - invT, ep1Coord.tree],
121134
+ ["*", invT, midpointVal.tree]
121135
+ ]).simplify();
121136
+ }
121137
+ } else {
121138
+ const slope = getConfiguredSlope(g2);
121139
+ const signedLength = getConfiguredSignedLength(g2);
121140
+ const direction = directionFromSlope(slope);
121141
+ if (direction === null) {
121142
+ for (let arrayKey of arrayKeys) {
121143
+ unconstrainedEndpoints[arrayKey] = Context.fromAst("_");
121144
+ }
121145
+ let result22 = { setValue: { unconstrainedEndpoints } };
121146
+ if (sendDiagnostics.length > 0) {
121147
+ result22.sendDiagnostics = sendDiagnostics;
121148
+ }
121149
+ return result22;
121150
+ }
121151
+ const [dirX, dirY] = direction;
121152
+ if (g2.numEndpointsSpecified === 1 && !g2.midpointSpecified) {
121153
+ for (let arrayKey of arrayKeys) {
121154
+ let [pointInd, dim] = arrayKey.split(",");
121155
+ let varEnding = "1_" + (Number(dim) + 1);
121156
+ let ep1Coord = dependencyValuesByKey[arrayKey].ep1Coord.stateValues["pointX" + varEnding];
121157
+ if (!ep1Coord) {
121158
+ unconstrainedEndpoints[arrayKey] = Context.fromAst("_");
121159
+ continue;
121160
+ }
121161
+ if (pointInd === "0") {
121162
+ unconstrainedEndpoints[arrayKey] = ep1Coord;
121163
+ } else {
121164
+ let delta = signedLength * getDirectionComponent(dim, dirX, dirY);
121165
+ unconstrainedEndpoints[arrayKey] = Context.fromAst(["+", ep1Coord.tree, delta]).simplify();
121166
+ }
121167
+ }
121168
+ } else if (g2.midpointSpecified) {
121169
+ const po2 = g2.midpointOffset;
121170
+ for (let arrayKey of arrayKeys) {
121171
+ let [pointInd, dim] = arrayKey.split(",");
121172
+ let midpointCoordVal = dependencyValuesByKey[arrayKey].midpointCoord?.stateValues["x" + (Number(dim) + 1)];
121173
+ if (!midpointCoordVal) {
121174
+ unconstrainedEndpoints[arrayKey] = Context.fromAst("_");
121175
+ continue;
121176
+ }
121177
+ let dir = getDirectionComponent(dim, dirX, dirY);
121178
+ if (pointInd === "0") {
121179
+ let coeff = (1 + po2) / 2 * signedLength * dir;
121180
+ unconstrainedEndpoints[arrayKey] = Context.fromAst([
121181
+ "+",
121182
+ midpointCoordVal.tree,
121183
+ -coeff
121184
+ ]).simplify();
121185
+ } else {
121186
+ let coeff = (1 - po2) / 2 * signedLength * dir;
121187
+ unconstrainedEndpoints[arrayKey] = Context.fromAst([
121188
+ "+",
121189
+ midpointCoordVal.tree,
121190
+ coeff
121191
+ ]).simplify();
121192
+ }
121193
+ }
120621
121194
  } else {
120622
- essentialUnconstrainedEndpoints[arrayKey] = true;
121195
+ let ep1 = g2.essentialEp1 ?? [
121196
+ Context.fromAst(0),
121197
+ Context.fromAst(0)
121198
+ ];
121199
+ for (let arrayKey of arrayKeys) {
121200
+ let [pointInd, dim] = arrayKey.split(",");
121201
+ let ep1Coord = ep1[Number(dim)] ?? Context.fromAst(0);
121202
+ if (pointInd === "0") {
121203
+ unconstrainedEndpoints[arrayKey] = ep1Coord;
121204
+ } else {
121205
+ let dir = getDirectionComponent(
121206
+ dim,
121207
+ dirX,
121208
+ dirY
121209
+ );
121210
+ let delta = signedLength * dir;
121211
+ unconstrainedEndpoints[arrayKey] = Context.fromAst(["+", ep1Coord.tree, delta]).simplify();
121212
+ }
121213
+ }
120623
121214
  }
120624
121215
  }
120625
- let result2 = {};
120626
- if (Object.keys(unconstrainedEndpoints).length > 0) {
120627
- result2.setValue = { unconstrainedEndpoints };
120628
- }
120629
- if (Object.keys(essentialUnconstrainedEndpoints).length > 0) {
120630
- result2.useEssentialOrDefaultValue = {
120631
- unconstrainedEndpoints: essentialUnconstrainedEndpoints
120632
- };
121216
+ let result2 = { setValue: { unconstrainedEndpoints } };
121217
+ if (sendDiagnostics.length > 0) {
121218
+ result2.sendDiagnostics = sendDiagnostics;
120633
121219
  }
120634
121220
  return result2;
120635
121221
  },
120636
121222
  async inverseArrayDefinitionByKey({
120637
121223
  desiredStateVariableValues,
121224
+ globalDependencyValues,
120638
121225
  dependencyValuesByKey,
120639
121226
  dependencyNamesByKey,
120640
121227
  initialChange,
120641
- stateValues
121228
+ stateValues,
121229
+ workspace,
121230
+ arraySize: arraySize2
120642
121231
  }) {
121232
+ if (!globalDependencyValues?.basedOnSlopeOrMidpoint) {
121233
+ let instructions2 = [];
121234
+ for (let arrayKey in desiredStateVariableValues.unconstrainedEndpoints) {
121235
+ let [pointInd, dim] = arrayKey.split(",");
121236
+ let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
121237
+ if (dependencyValuesByKey[arrayKey].endpointsAttr !== null && dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding]) {
121238
+ instructions2.push({
121239
+ setDependency: dependencyNamesByKey[arrayKey].endpointsAttr,
121240
+ desiredValue: desiredStateVariableValues.unconstrainedEndpoints[arrayKey],
121241
+ childIndex: 0,
121242
+ variableIndex: 0
121243
+ });
121244
+ } else {
121245
+ instructions2.push({
121246
+ setEssentialValue: "unconstrainedEndpoints",
121247
+ value: {
121248
+ [arrayKey]: desiredStateVariableValues.unconstrainedEndpoints[arrayKey]
121249
+ }
121250
+ });
121251
+ }
121252
+ }
121253
+ return { success: true, instructions: instructions2 };
121254
+ }
121255
+ const g2 = globalDependencyValues;
121256
+ const numDim = g2.numDimensions ?? 2;
121257
+ workspace ??= {};
121258
+ Object.assign(
121259
+ workspace,
121260
+ desiredStateVariableValues.unconstrainedEndpoints
121261
+ );
121262
+ const desiredUnconstrainedEndpoints = workspace;
121263
+ const desiredKeys = Object.keys(desiredUnconstrainedEndpoints);
121264
+ const onlyEp1Desired = desiredKeys.every(
121265
+ (k2) => k2.startsWith("0,")
121266
+ );
121267
+ const onlyEp2Desired = desiredKeys.every(
121268
+ (k2) => k2.startsWith("1,")
121269
+ );
120643
121270
  let instructions = [];
120644
- for (let arrayKey in desiredStateVariableValues.unconstrainedEndpoints) {
120645
- let [pointInd, dim] = arrayKey.split(",");
120646
- let varEnding = Number(pointInd) + 1 + "_" + (Number(dim) + 1);
120647
- if (dependencyValuesByKey[arrayKey].endpointsAttr !== null && dependencyValuesByKey[arrayKey].endpointsAttr.stateValues["pointX" + varEnding]) {
120648
- instructions.push({
120649
- setDependency: dependencyNamesByKey[arrayKey].endpointsAttr,
120650
- desiredValue: desiredStateVariableValues.unconstrainedEndpoints[arrayKey],
120651
- childIndex: 0,
120652
- variableIndex: 0
120653
- });
120654
- } else {
120655
- instructions.push({
120656
- setEssentialValue: "unconstrainedEndpoints",
120657
- value: {
120658
- [arrayKey]: desiredStateVariableValues.unconstrainedEndpoints[arrayKey]
121271
+ const numEndpointsSpecified = g2.numEndpointsSpecified;
121272
+ const midpointSpecified = g2.midpointSpecified;
121273
+ if (numEndpointsSpecified === 1 && midpointSpecified) {
121274
+ const tT = (1 + g2.midpointOffset) / 2;
121275
+ if (tT === 0) {
121276
+ if (!onlyEp1Desired) {
121277
+ return { success: false };
121278
+ }
121279
+ for (let arrayKey of desiredKeys) {
121280
+ instructions.push({
121281
+ setDependency: dependencyNamesByKey[arrayKey].ep1Coord,
121282
+ desiredValue: desiredUnconstrainedEndpoints[arrayKey],
121283
+ variableIndex: 0
121284
+ });
121285
+ }
121286
+ return { success: true, instructions };
121287
+ }
121288
+ let currentEndpoints = await stateValues.endpoints;
121289
+ let [ep1Num, ep2Num] = getNumericEndpointPair(
121290
+ desiredUnconstrainedEndpoints,
121291
+ currentEndpoints,
121292
+ numDim
121293
+ );
121294
+ if (!ep1Num.every(Number.isFinite) || !ep2Num.every(Number.isFinite)) {
121295
+ return { success: false };
121296
+ }
121297
+ for (let arrayKey of desiredKeys) {
121298
+ let [pointInd] = arrayKey.split(",").map(Number);
121299
+ if (pointInd === 0) {
121300
+ instructions.push({
121301
+ setDependency: dependencyNamesByKey[arrayKey].ep1Coord,
121302
+ desiredValue: desiredUnconstrainedEndpoints[arrayKey],
121303
+ variableIndex: 0
121304
+ });
121305
+ }
121306
+ }
121307
+ const M_new = ep1Num.map(
121308
+ (value, dim) => value + tT * (ep2Num[dim] - value)
121309
+ );
121310
+ addMidpointInstructions({
121311
+ instructions,
121312
+ dependencyNamesByKey,
121313
+ midpointCoords: M_new
121314
+ });
121315
+ return { success: true, instructions };
121316
+ }
121317
+ if (numEndpointsSpecified === 1 && !midpointSpecified) {
121318
+ if (!onlyEp2Desired) {
121319
+ for (let arrayKey of desiredKeys) {
121320
+ let [pointInd] = arrayKey.split(",").map(Number);
121321
+ if (pointInd === 0) {
121322
+ instructions.push({
121323
+ setDependency: dependencyNamesByKey[arrayKey].ep1Coord,
121324
+ desiredValue: desiredUnconstrainedEndpoints[arrayKey],
121325
+ variableIndex: 0
121326
+ });
120659
121327
  }
121328
+ }
121329
+ }
121330
+ if (!onlyEp1Desired) {
121331
+ let currentEndpoints = await stateValues.endpoints;
121332
+ let [ep1Num, ep2Num] = getNumericEndpointPair(
121333
+ desiredUnconstrainedEndpoints,
121334
+ currentEndpoints
121335
+ );
121336
+ if (ep1Num.every(Number.isFinite) && ep2Num.every(Number.isFinite)) {
121337
+ addSlopeAndLengthInstructions({
121338
+ instructions,
121339
+ globalDependencyValues: g2,
121340
+ endpoint1: ep1Num,
121341
+ endpoint2: ep2Num
121342
+ });
121343
+ }
121344
+ }
121345
+ } else if (midpointSpecified) {
121346
+ const po2 = g2.midpointOffset;
121347
+ const tT = (1 + po2) / 2;
121348
+ let T_new;
121349
+ if (onlyEp1Desired) {
121350
+ const slope = getConfiguredSlope(g2);
121351
+ const L2 = getConfiguredSignedLength(g2);
121352
+ const direction = directionFromSlope(slope);
121353
+ if (direction === null) {
121354
+ return { success: false };
121355
+ }
121356
+ const [dirX2, dirY2] = direction;
121357
+ let currentEndpoints = await stateValues.endpoints;
121358
+ const [ep1Desired] = getNumericEndpointPair(
121359
+ desiredUnconstrainedEndpoints,
121360
+ currentEndpoints,
121361
+ numDim,
121362
+ [0]
121363
+ );
121364
+ T_new = ep1Desired.map(
121365
+ (value, dim) => value + tT * L2 * getDirectionComponent(dim, dirX2, dirY2)
121366
+ );
121367
+ if (!T_new.every(Number.isFinite)) {
121368
+ return { success: false };
121369
+ }
121370
+ } else {
121371
+ let currentEndpoints = await stateValues.endpoints;
121372
+ let [ep1Num, ep2Num] = getNumericEndpointPair(
121373
+ desiredUnconstrainedEndpoints,
121374
+ currentEndpoints,
121375
+ numDim
121376
+ );
121377
+ if (!ep1Num.every(Number.isFinite) || !ep2Num.every(Number.isFinite)) {
121378
+ return { success: false };
121379
+ }
121380
+ T_new = ep1Num.map(
121381
+ (value, dim) => value + tT * (ep2Num[dim] - value)
121382
+ );
121383
+ addSlopeAndLengthInstructions({
121384
+ instructions,
121385
+ globalDependencyValues: g2,
121386
+ endpoint1: ep1Num,
121387
+ endpoint2: ep2Num
120660
121388
  });
120661
121389
  }
121390
+ addMidpointInstructions({
121391
+ instructions,
121392
+ dependencyNamesByKey,
121393
+ midpointCoords: T_new
121394
+ });
121395
+ } else {
121396
+ if (!onlyEp2Desired) {
121397
+ for (let arrayKey of desiredKeys) {
121398
+ let [pointInd, dim] = arrayKey.split(",").map(Number);
121399
+ if (pointInd === 0) {
121400
+ instructions.push({
121401
+ setDependency: "essentialEp1",
121402
+ desiredValue: {
121403
+ [String(dim)]: desiredUnconstrainedEndpoints[arrayKey]
121404
+ }
121405
+ });
121406
+ }
121407
+ }
121408
+ }
121409
+ if (!onlyEp1Desired) {
121410
+ let currentEndpoints = await stateValues.endpoints;
121411
+ let [ep1Num, ep2Num] = getNumericEndpointPair(
121412
+ desiredUnconstrainedEndpoints,
121413
+ currentEndpoints
121414
+ );
121415
+ if (ep1Num.every(Number.isFinite) && ep2Num.every(Number.isFinite)) {
121416
+ addSlopeAndLengthInstructions({
121417
+ instructions,
121418
+ globalDependencyValues: g2,
121419
+ endpoint1: ep1Num,
121420
+ endpoint2: ep2Num
121421
+ });
121422
+ }
121423
+ }
120662
121424
  }
120663
- return {
120664
- success: true,
120665
- instructions
120666
- };
121425
+ return { success: true, instructions };
120667
121426
  }
120668
121427
  };
120669
121428
  stateVariableDefinitions.haveConstrainedEndpoints = {
@@ -120954,7 +121713,7 @@ class LineSegment extends GraphicalComponent {
120954
121713
  }
120955
121714
  };
120956
121715
  stateVariableDefinitions.length = {
120957
- description: "The length of the line segment.",
121716
+ description: "The Euclidean length of the line segment (always non-negative).",
120958
121717
  public: true,
120959
121718
  isLocation: true,
120960
121719
  shadowingInstructions: {
@@ -121215,7 +121974,7 @@ class LineSegment extends GraphicalComponent {
121215
121974
  }
121216
121975
  };
121217
121976
  stateVariableDefinitions.slope = {
121218
- description: "The slope of the line segment (2D only).",
121977
+ description: "The slope of the line segment in the x-y plane; returns NaN when the segment is not 2D.",
121219
121978
  public: true,
121220
121979
  isLocation: true,
121221
121980
  shadowingInstructions: {
@@ -121223,9 +121982,9 @@ class LineSegment extends GraphicalComponent {
121223
121982
  addAttributeComponentsShadowingStateVariables: returnNumberDisplayAttributeComponentShadowing()
121224
121983
  },
121225
121984
  returnDependencies: () => ({
121226
- numericalEndpoints: {
121985
+ endpoints: {
121227
121986
  dependencyType: "stateVariable",
121228
- variableName: "numericalEndpoints"
121987
+ variableName: "endpoints"
121229
121988
  },
121230
121989
  numDimensions: {
121231
121990
  dependencyType: "stateVariable",
@@ -121236,9 +121995,206 @@ class LineSegment extends GraphicalComponent {
121236
121995
  if (dependencyValues.numDimensions !== 2) {
121237
121996
  return { setValue: { slope: NaN } };
121238
121997
  }
121239
- let ps = dependencyValues.numericalEndpoints;
121240
- let slope = (ps[1][1] - ps[0][1]) / (ps[1][0] - ps[0][0]);
121998
+ let ep = dependencyValues.endpoints;
121999
+ let A1 = ep[0][0].evaluate_to_constant();
122000
+ let A2 = ep[0][1].evaluate_to_constant();
122001
+ let B1 = ep[1][0].evaluate_to_constant();
122002
+ let B2 = ep[1][1].evaluate_to_constant();
122003
+ let slope = (B2 - A2) / (B1 - A1);
121241
122004
  return { setValue: { slope } };
122005
+ },
122006
+ inverseDefinition({
122007
+ desiredStateVariableValues,
122008
+ dependencyValues
122009
+ }) {
122010
+ if (dependencyValues.numDimensions !== 2) {
122011
+ return { success: false };
122012
+ }
122013
+ let ep = dependencyValues.endpoints;
122014
+ let A1 = ep[0][0].evaluate_to_constant();
122015
+ let A2 = ep[0][1].evaluate_to_constant();
122016
+ let B1 = ep[1][0].evaluate_to_constant();
122017
+ let B2 = ep[1][1].evaluate_to_constant();
122018
+ if (!Number.isFinite(A1) || !Number.isFinite(A2) || !Number.isFinite(B1) || !Number.isFinite(B2)) {
122019
+ return { success: false };
122020
+ }
122021
+ let cx = (A1 + B1) / 2;
122022
+ let cy = (A2 + B2) / 2;
122023
+ let L2 = Math.sqrt((B1 - A1) ** 2 + (B2 - A2) ** 2);
122024
+ if (L2 === 0) {
122025
+ return { success: false };
122026
+ }
122027
+ let m2 = desiredStateVariableValues.slope;
122028
+ if (m2 instanceof Context.class) {
122029
+ m2 = m2.evaluate_to_constant();
122030
+ }
122031
+ if (Number.isNaN(m2)) {
122032
+ return { success: false };
122033
+ }
122034
+ const direction = directionFromSlope(m2);
122035
+ if (direction === null) {
122036
+ return { success: false };
122037
+ }
122038
+ let [dirX, dirY] = direction;
122039
+ let currentDirX = (B1 - A1) / L2;
122040
+ let currentDirY = (B2 - A2) / L2;
122041
+ if (Number.isFinite(m2) && currentDirX * dirX + currentDirY * dirY < 0) {
122042
+ dirX = -dirX;
122043
+ dirY = -dirY;
122044
+ }
122045
+ let half = L2 / 2;
122046
+ let newEp1 = [
122047
+ Context.fromAst(cx - half * dirX),
122048
+ Context.fromAst(cy - half * dirY)
122049
+ ];
122050
+ let newEp2 = [
122051
+ Context.fromAst(cx + half * dirX),
122052
+ Context.fromAst(cy + half * dirY)
122053
+ ];
122054
+ return {
122055
+ success: true,
122056
+ instructions: [
122057
+ {
122058
+ setDependency: "endpoints",
122059
+ desiredValue: [newEp1, newEp2]
122060
+ }
122061
+ ]
122062
+ };
122063
+ }
122064
+ };
122065
+ stateVariableDefinitions.midpoint = {
122066
+ description: "The midpoint of the line segment, i.e. the average of its endpoints. When the midpoint attribute is set together with a nonzero midpointOffset, this actual midpoint differs from the point given by the midpoint attribute.",
122067
+ public: true,
122068
+ isLocation: true,
122069
+ shadowingInstructions: {
122070
+ createComponentOfType: "math",
122071
+ addAttributeComponentsShadowingStateVariables: returnNumberDisplayAttributeComponentShadowing(),
122072
+ returnWrappingComponents(prefix) {
122073
+ if (prefix === "midpointX") {
122074
+ return [];
122075
+ } else {
122076
+ return [
122077
+ [
122078
+ "point",
122079
+ {
122080
+ componentType: "mathList",
122081
+ isAttributeNamed: "xs"
122082
+ }
122083
+ ]
122084
+ ];
122085
+ }
122086
+ }
122087
+ },
122088
+ isArray: true,
122089
+ numDimensions: 1,
122090
+ indexAliases: [["x", "y", "z"]],
122091
+ entryPrefixes: ["midpointX"],
122092
+ returnEntryDimensions: () => 0,
122093
+ getArrayKeysFromVarName({
122094
+ arrayEntryPrefix,
122095
+ varEnding,
122096
+ arraySize: arraySize2
122097
+ }) {
122098
+ let ind = Number(varEnding) - 1;
122099
+ if (!Number.isInteger(ind) || ind < 0) {
122100
+ return [];
122101
+ }
122102
+ if (arraySize2) {
122103
+ return ind < arraySize2[0] ? [String(ind)] : [];
122104
+ }
122105
+ return [String(ind)];
122106
+ },
122107
+ arrayVarNameFromPropIndex(propIndex, varName) {
122108
+ if (varName === "midpoint") {
122109
+ return "midpointX" + propIndex[0];
122110
+ }
122111
+ return null;
122112
+ },
122113
+ returnArraySizeDependencies: () => ({
122114
+ numDimensions: {
122115
+ dependencyType: "stateVariable",
122116
+ variableName: "numDimensions"
122117
+ }
122118
+ }),
122119
+ returnArraySize({ dependencyValues }) {
122120
+ return [dependencyValues.numDimensions];
122121
+ },
122122
+ returnArrayDependenciesByKey() {
122123
+ return {
122124
+ globalDependencies: {
122125
+ endpoints: {
122126
+ dependencyType: "stateVariable",
122127
+ variableName: "endpoints"
122128
+ },
122129
+ numDimensions: {
122130
+ dependencyType: "stateVariable",
122131
+ variableName: "numDimensions"
122132
+ }
122133
+ }
122134
+ };
122135
+ },
122136
+ arrayDefinitionByKey({ globalDependencyValues, arrayKeys }) {
122137
+ let midpoint = {};
122138
+ let ep1 = globalDependencyValues.endpoints[0];
122139
+ let ep2 = globalDependencyValues.endpoints[1];
122140
+ for (let arrayKey of arrayKeys) {
122141
+ let dim = Number(arrayKey);
122142
+ let v1 = ep1[dim].evaluate_to_constant();
122143
+ let v2 = ep2[dim].evaluate_to_constant();
122144
+ if (Number.isFinite(v1) && Number.isFinite(v2)) {
122145
+ midpoint[arrayKey] = Context.fromAst((v1 + v2) / 2);
122146
+ } else {
122147
+ midpoint[arrayKey] = Context.fromAst([
122148
+ "/",
122149
+ ["+", ep1[dim].tree, ep2[dim].tree],
122150
+ 2
122151
+ ]);
122152
+ }
122153
+ }
122154
+ return { setValue: { midpoint } };
122155
+ },
122156
+ inverseArrayDefinitionByKey({
122157
+ desiredStateVariableValues,
122158
+ globalDependencyValues
122159
+ }) {
122160
+ let ep1 = globalDependencyValues.endpoints[0];
122161
+ let ep2 = globalDependencyValues.endpoints[1];
122162
+ let desiredEndpoints = {};
122163
+ for (let dimString in desiredStateVariableValues.midpoint) {
122164
+ let d2 = Number(dimString);
122165
+ let currentMidpoint = Context.fromAst([
122166
+ "/",
122167
+ ["+", ep1[d2].tree, ep2[d2].tree],
122168
+ 2
122169
+ ]);
122170
+ let desiredMidpoint = convertValueToMathExpression(
122171
+ desiredStateVariableValues.midpoint[dimString]
122172
+ );
122173
+ let delta = Context.fromAst([
122174
+ "+",
122175
+ desiredMidpoint.tree,
122176
+ ["-", currentMidpoint.tree]
122177
+ ]);
122178
+ desiredEndpoints["0," + d2] = Context.fromAst([
122179
+ "+",
122180
+ ep1[d2].tree,
122181
+ delta.tree
122182
+ ]);
122183
+ desiredEndpoints["1," + d2] = Context.fromAst([
122184
+ "+",
122185
+ ep2[d2].tree,
122186
+ delta.tree
122187
+ ]);
122188
+ }
122189
+ return {
122190
+ success: true,
122191
+ instructions: [
122192
+ {
122193
+ setDependency: "endpoints",
122194
+ desiredValue: desiredEndpoints
122195
+ }
122196
+ ]
122197
+ };
121242
122198
  }
121243
122199
  };
121244
122200
  return stateVariableDefinitions;
@@ -121253,8 +122209,10 @@ class LineSegment extends GraphicalComponent {
121253
122209
  }
121254
122210
  ];
121255
122211
  async moveLineSegmentSinglePoint({
122212
+ coords,
121256
122213
  x: x2,
121257
122214
  y: y2,
122215
+ z: z2,
121258
122216
  pointRole,
121259
122217
  transient,
121260
122218
  skippable,
@@ -121263,15 +122221,19 @@ class LineSegment extends GraphicalComponent {
121263
122221
  sourceInformation = {},
121264
122222
  skipRendererUpdate = false
121265
122223
  }) {
121266
- if (!Number.isFinite(x2) || !Number.isFinite(y2)) {
122224
+ let pointCoords = coords ?? [x2, y2];
122225
+ if (coords === void 0 && z2 !== void 0) {
122226
+ pointCoords.push(z2);
122227
+ }
122228
+ if (pointCoords.length < 2 || !Number.isFinite(pointCoords[0]) || !Number.isFinite(pointCoords[1]) || pointCoords.slice(2).some((coord) => coord !== void 0 && !Number.isFinite(coord))) {
121267
122229
  console.warn(
121268
- `Invalid endpoint coordinates for line segment move: x=${x2}, y=${y2}`
122230
+ `Invalid endpoint coordinates for line segment move: ${pointCoords.join(", ")}`
121269
122231
  );
121270
122232
  return;
121271
122233
  }
121272
122234
  if (pointRole === "endpoint1") {
121273
122235
  return await this.moveLineSegment({
121274
- point1coords: [x2, y2],
122236
+ point1coords: pointCoords,
121275
122237
  transient,
121276
122238
  skippable,
121277
122239
  actionId,
@@ -121281,7 +122243,7 @@ class LineSegment extends GraphicalComponent {
121281
122243
  });
121282
122244
  } else if (pointRole === "endpoint2") {
121283
122245
  return await this.moveLineSegment({
121284
- point2coords: [x2, y2],
122246
+ point2coords: pointCoords,
121285
122247
  transient,
121286
122248
  skippable,
121287
122249
  actionId,
@@ -121316,14 +122278,39 @@ class LineSegment extends GraphicalComponent {
121316
122278
  return;
121317
122279
  }
121318
122280
  }
122281
+ const numDimensions = await this.stateValues.numDimensions;
122282
+ let numericalEndpoints = await this.stateValues.numericalEndpoints;
122283
+ if (point1coords !== void 0) {
122284
+ point1coords = mergePointCoords(
122285
+ point1coords,
122286
+ numericalEndpoints[0],
122287
+ numDimensions
122288
+ );
122289
+ }
122290
+ if (point2coords !== void 0) {
122291
+ point2coords = mergePointCoords(
122292
+ point2coords,
122293
+ numericalEndpoints[1],
122294
+ numDimensions
122295
+ );
122296
+ }
122297
+ if (await this.stateValues.basedOnSlopeOrMidpoint) {
122298
+ if (point1coords !== void 0 && point2coords === void 0) {
122299
+ point2coords = numericalEndpoints[1];
122300
+ } else if (point2coords !== void 0 && point1coords === void 0) {
122301
+ point1coords = numericalEndpoints[0];
122302
+ }
122303
+ }
121319
122304
  let newComponents = {};
121320
122305
  if (point1coords !== void 0) {
121321
- newComponents["0,0"] = Context.fromAst(point1coords[0]);
121322
- newComponents["0,1"] = Context.fromAst(point1coords[1]);
122306
+ for (let dim = 0; dim < numDimensions; dim++) {
122307
+ newComponents[`0,${dim}`] = Context.fromAst(point1coords[dim]);
122308
+ }
121323
122309
  }
121324
122310
  if (point2coords !== void 0) {
121325
- newComponents["1,0"] = Context.fromAst(point2coords[0]);
121326
- newComponents["1,1"] = Context.fromAst(point2coords[1]);
122311
+ for (let dim = 0; dim < numDimensions; dim++) {
122312
+ newComponents[`1,${dim}`] = Context.fromAst(point2coords[dim]);
122313
+ }
121327
122314
  }
121328
122315
  if (transient) {
121329
122316
  await this.coreFunctions.performUpdate({
@@ -121397,12 +122384,11 @@ class LineSegment extends GraphicalComponent {
121397
122384
  }
121398
122385
  let newPointComponents = {};
121399
122386
  for (let ind in newNumericalPoints) {
121400
- newPointComponents[ind + ",0"] = Context.fromAst(
121401
- newNumericalPoints[ind][0]
121402
- );
121403
- newPointComponents[ind + ",1"] = Context.fromAst(
121404
- newNumericalPoints[ind][1]
121405
- );
122387
+ for (let dim = 0; dim < numDimensions; dim++) {
122388
+ newPointComponents[`${ind},${dim}`] = Context.fromAst(
122389
+ newNumericalPoints[ind][dim]
122390
+ );
122391
+ }
121406
122392
  }
121407
122393
  let newInstructions = [
121408
122394
  {
@@ -229508,4 +230494,4 @@ export {
229508
230494
  getDefaultExportFromCjs as g,
229509
230495
  updateSyntaxFromV06toV07 as u
229510
230496
  };
229511
- //# sourceMappingURL=index-DIXIAZMT.js.map
230497
+ //# sourceMappingURL=index-BdPydNFg.js.map