Skip to content

Commit adfa535

Browse files
committed
plot enhancements
1 parent 299ddb3 commit adfa535

File tree

3 files changed

+82
-27
lines changed

3 files changed

+82
-27
lines changed

math/numericalAnalysis/numericalAnalysisService.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,19 +206,22 @@ export const findComplexRootsOfPolynomial = function (termsArray) {
206206
};
207207

208208
//
209-
// Laplace inversion
209+
// Laplace-transform inversion
210210
//
211211

212212
/**
213-
* Using an implementation of the Talbot numerical method for Laplace inversion,
214-
* after taking as input the s-domain Laplace transform function F(s),
213+
* Using an implementation of the Talbot numerical method for Laplace-transform inversion,
214+
* after taking as input the s-domain function F(s),
215215
* compute the t-domain function value f(t) at time t
216216
*
217217
* It uses the 'Complex' library
218218
*/
219-
export const TalbotMethod = function (F, t, N) {
219+
export const talbotMethodForLaplaceTransformInversion = function (F, t, N) {
220220
if (t <= 0) {
221-
console.error("TalbotMethod()", "t must be positive");
221+
console.error(
222+
"talbotMethodForLaplaceTransformInversion()",
223+
"t must be positive"
224+
);
222225
return;
223226
}
224227

view/plots/nyquistPlot.js

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export default class NyquistPlot {
4545

4646
#nyquistObserver;
4747

48+
//plot colors
49+
#curveSegmentColor1 = "#4682b4";
50+
#curveSegmentColor2 = "#aaaaaa";
4851
constructor(
4952
plotContainerDomElement,
5053
numeratorTermsArray,
@@ -156,8 +159,6 @@ export default class NyquistPlot {
156159
}
157160

158161
createNyquistPlot() {
159-
const arrowsNumber = 100;
160-
161162
let plotBoundRect = this.#nyquistPlotDomElement.getBoundingClientRect();
162163
let plotWidth = plotBoundRect.width;
163164
let plotHeight = plotBoundRect.height;
@@ -171,6 +172,9 @@ export default class NyquistPlot {
171172
// const minImag = Math.min(...imags);
172173
// const maxImag = Math.max(...imags);
173174

175+
const arrowsNumber = 100;
176+
const maxAllowedDistanceOfConsecutivePoints = 50;
177+
174178
//set limits for coordinates of plotted points
175179
const xMax = 10 ** 4;
176180
const yMax = 10 ** 4;
@@ -198,31 +202,41 @@ export default class NyquistPlot {
198202
// )(scope.x);
199203
// },
200204
// },
201-
{
202-
points: this.#curvePoints
203-
.filter((x) => x[0] > 0 && x[1] < xMax && x[2] < yMax)
204-
.map((x) => [x[1], x[2]]),
205-
// color: "red",
206-
fnType: "points",
207-
graphType: "polyline",
208-
},
209-
{
210-
points: this.#curvePoints
211-
.filter((x) => x[0] < 0 && x[1] > -xMax && x[2] > -yMax)
212-
.map((x) => [x[1], x[2]]),
213-
fnType: "points",
214-
graphType: "polyline",
215-
color: "gray",
216-
},
217205
// {
218206
// graphType: "polyline",
219-
// color: "gray",
220207
// fn: (scope) => {
221208
// return linearInterpolationOfCurvePoints(
222209
// this.#curvePoints.filter((x) => x[0] < 0).map((x) => [x[1], x[2]])
223210
// )(scope.x);
224211
// },
212+
// color: this.#curveSegmentColor2,
225213
// },
214+
...divideNyquistCurveIntoSegments(
215+
this.#curvePoints
216+
.filter((x) => x[0] > 0 && x[1] < xMax && x[2] < yMax)
217+
.map((x) => [x[1], x[2]]),
218+
maxAllowedDistanceOfConsecutivePoints
219+
).map((curvePointsSegment) => {
220+
return {
221+
points: curvePointsSegment,
222+
fnType: "points",
223+
graphType: "polyline",
224+
color: this.#curveSegmentColor1,
225+
};
226+
}),
227+
...divideNyquistCurveIntoSegments(
228+
this.#curvePoints
229+
.filter((x) => x[0] < 0 && x[1] > -xMax && x[2] > -yMax)
230+
.map((x) => [x[1], x[2]]),
231+
maxAllowedDistanceOfConsecutivePoints
232+
).map((curvePointsSegment) => {
233+
return {
234+
points: curvePointsSegment,
235+
fnType: "points",
236+
graphType: "polyline",
237+
color: this.#curveSegmentColor2,
238+
};
239+
}),
226240
{
227241
points: this.#zeros,
228242
fnType: "points",
@@ -409,7 +423,7 @@ const computeNyquistRealAndImagWFunctions = function (
409423
);
410424

411425
//
412-
// define magnitude & phase functions
426+
// define real & imag functions
413427
//
414428
const numReal = functionFromPolynomialTermsArray(
415429
polynomialEvaluatedWithWiRealTermsArray(numeratorTermsArray)
@@ -467,3 +481,41 @@ const computeStability = function (numeratorTermsArray, denominatorTermsArray) {
467481
}
468482
return stability;
469483
};
484+
485+
/**
486+
* Divide a Nyquist plot curve into multiple segments, in case
487+
* connections between two consecutive points of paths tending into inf
488+
* are expected to be made
489+
*
490+
* @returns an array of curve segments
491+
* (with each curve segment as an array of points)
492+
*/
493+
const divideNyquistCurveIntoSegments = (
494+
curvePoints,
495+
maxAllowedDistanceOfConsecutivePoints
496+
) => {
497+
const allSegments = [];
498+
let currentSegment = [];
499+
500+
for (let p of curvePoints) {
501+
if (currentSegment.length === 0) {
502+
currentSegment.push(p);
503+
} else {
504+
const lastP = currentSegment.slice(-1)[0];
505+
506+
if (
507+
(lastP[0] * p[0] < 0 || lastP[1] * p[1] < 0) &&
508+
Math.sqrt((lastP[0] - p[0]) ** 2 + (lastP[1] - p[1]) ** 2) >
509+
maxAllowedDistanceOfConsecutivePoints
510+
) {
511+
//segment end
512+
allSegments.push([...currentSegment]);
513+
currentSegment = [];
514+
}
515+
currentSegment.push(p);
516+
}
517+
}
518+
allSegments.push([...currentSegment]);
519+
520+
return allSegments;
521+
};

view/plots/timeDomainPlot.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import { tfEvaluatedWithComplexNumber } from "../../math/complexAnalysis/complexAnalysisService.js";
1010
import {
11-
TalbotMethod,
1211
linearInterpolationOfCurvePoints,
12+
talbotMethodForLaplaceTransformInversion,
1313
} from "../../math/numericalAnalysis/numericalAnalysisService.js";
1414
import { areAllTfTermsNumbers } from "../../util/commons.js";
1515
import { logMessages } from "../../util/loggingService.js";
@@ -105,7 +105,7 @@ export default class TimeDomainPlot {
105105

106106
for (let t = this.#tMin; t <= this.#tMax; t += step) {
107107
//new values
108-
newFunctionValue = TalbotMethod(
108+
newFunctionValue = talbotMethodForLaplaceTransformInversion(
109109
tfEvaluatedWithComplexNumber(
110110
this.#numeratorTermsArray,
111111
this.#denominatorTermsArray

0 commit comments

Comments
 (0)