From 3d12a8d9f8c11f9d54d1747ffdb3336ee63f23b6 Mon Sep 17 00:00:00 2001 From: Jonathan Olson Date: Thu, 13 Feb 2025 17:59:07 -0700 Subject: [PATCH] Converting dot Utils usage, see https://github.com/phetsims/dot/issues/4 --- doc/index.js | 4 +-- js/cag/ClippableFace.ts | 45 ++++++++++++++-------------- js/cag/IntegerEdge.ts | 10 +++---- js/cag/LinearEdge.ts | 6 ++-- js/clip/ClipSimplifier.ts | 8 ++--- js/clip/GridClipping.ts | 18 +++++------ js/render-program/RenderImage.ts | 8 ++--- js/webgpu/PerformanceTesting.ts | 4 +-- js/webgpu/compute/Executor.ts | 4 +-- js/webgpu/compute/TimestampLogger.ts | 4 +-- tests/playground.html | 8 ++--- 11 files changed, 60 insertions(+), 59 deletions(-) diff --git a/doc/index.js b/doc/index.js index 803c285..6196f6c 100644 --- a/doc/index.js +++ b/doc/index.js @@ -645,9 +645,9 @@ window.createSceneryDiagram = ( scene, width, height, needsWhiteBackground = fal // Oops, tricky to get these to match up exactly. const delta = v2( 108, 10 ); - const center = phet.dot.Utils.lineLineIntersection( v2( 10, 10 ), v2( 10, 10 ).plus( delta.perpendicular ), v2( 0, 64 ), v2( 128, 64 ) ); + const center = phet.dot.lineLineIntersection( v2( 10, 10 ), v2( 10, 10 ).plus( delta.perpendicular ), v2( 0, 64 ), v2( 128, 64 ) ); const radius = delta.magnitude; - const rightPoint = phet.dot.Utils.lineLineIntersection( center, center.plus( delta ), v2( 128, 0 ), v2( 128, 128 ) ); + const rightPoint = phet.dot.lineLineIntersection( center, center.plus( delta ), v2( 128, 0 ), v2( 128, 128 ) ); const radial = new RadialGradient( center.x, center.y, 0, center.x, center.y, radius ); addColorStops( radial ); diff --git a/js/cag/ClippableFace.ts b/js/cag/ClippableFace.ts index 7623b8e..4bdfe0e 100644 --- a/js/cag/ClippableFace.ts +++ b/js/cag/ClippableFace.ts @@ -15,7 +15,7 @@ import Bounds2 from '../../../dot/js/Bounds2.js'; import Matrix3 from '../../../dot/js/Matrix3.js'; import Range from '../../../dot/js/Range.js'; -import Utils from '../../../dot/js/Utils.js'; +import { roundSymmetric } from '../../../dot/js/util/roundSymmetric.js'; import Vector2 from '../../../dot/js/Vector2.js'; import Shape from '../../../kite/js/Shape.js'; import IntentionalAny from '../../../phet-core/js/types/IntentionalAny.js'; @@ -27,6 +27,7 @@ import { StripeClipping } from '../clip/StripeClipping.js'; import { PolygonBilinear } from '../raster/PolygonBilinear.js'; import { PolygonMitchellNetravali } from '../raster/PolygonMitchellNetravali.js'; import { LinearEdge, SerializedLinearEdge } from './LinearEdge.js'; +import { solveQuadraticRootsReal } from '../../../dot/js/util/solveQuadraticRootsReal.js'; // TODO: assertions that all types of ClippableFace give the same results for the same methods @@ -838,13 +839,13 @@ export class EdgedFace implements ClippableFace { const edge = this.edges[ i ]; const startPoint = new Vector2( - Utils.roundSymmetric( edge.startPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( edge.startPoint.y / epsilon ) * epsilon + roundSymmetric( edge.startPoint.x / epsilon ) * epsilon, + roundSymmetric( edge.startPoint.y / epsilon ) * epsilon ); const endPoint = new Vector2( - Utils.roundSymmetric( edge.endPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( edge.endPoint.y / epsilon ) * epsilon + roundSymmetric( edge.endPoint.x / epsilon ) * epsilon, + roundSymmetric( edge.endPoint.y / epsilon ) * epsilon ); if ( !startPoint.equals( endPoint ) ) { @@ -1674,13 +1675,13 @@ export class EdgedClippedFace implements ClippableFace { const edge = this.edges[ i ]; const startPoint = new Vector2( - Utils.roundSymmetric( edge.startPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( edge.startPoint.y / epsilon ) * epsilon + roundSymmetric( edge.startPoint.x / epsilon ) * epsilon, + roundSymmetric( edge.startPoint.y / epsilon ) * epsilon ); const endPoint = new Vector2( - Utils.roundSymmetric( edge.endPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( edge.endPoint.y / epsilon ) * epsilon + roundSymmetric( edge.endPoint.x / epsilon ) * epsilon, + roundSymmetric( edge.endPoint.y / epsilon ) * epsilon ); if ( !startPoint.equals( endPoint ) ) { @@ -1691,13 +1692,13 @@ export class EdgedClippedFace implements ClippableFace { // TODO: more code sharing? this.forEachImplicitEdge( ( startPoint, endPoint ) => { const roundedStartPoint = new Vector2( - Utils.roundSymmetric( startPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( startPoint.y / epsilon ) * epsilon + roundSymmetric( startPoint.x / epsilon ) * epsilon, + roundSymmetric( startPoint.y / epsilon ) * epsilon ); const roundedEndPoint = new Vector2( - Utils.roundSymmetric( endPoint.x / epsilon ) * epsilon, - Utils.roundSymmetric( endPoint.y / epsilon ) * epsilon + roundSymmetric( endPoint.x / epsilon ) * epsilon, + roundSymmetric( endPoint.y / epsilon ) * epsilon ); if ( !roundedStartPoint.equals( roundedEndPoint ) ) { @@ -1707,10 +1708,10 @@ export class EdgedClippedFace implements ClippableFace { return EdgedClippedFace.fromEdgesWithoutCheck( edges, - Utils.roundSymmetric( this.minX / epsilon ) * epsilon, - Utils.roundSymmetric( this.minY / epsilon ) * epsilon, - Utils.roundSymmetric( this.maxX / epsilon ) * epsilon, - Utils.roundSymmetric( this.maxY / epsilon ) * epsilon + roundSymmetric( this.minX / epsilon ) * epsilon, + roundSymmetric( this.minY / epsilon ) * epsilon, + roundSymmetric( this.maxX / epsilon ) * epsilon, + roundSymmetric( this.maxY / epsilon ) * epsilon ); } @@ -2440,8 +2441,8 @@ export class PolygonalFace implements ClippableFace { public getRounded( epsilon: number ): PolygonalFace { return new PolygonalFace( this.polygons.map( polygon => polygon.map( vertex => { return new Vector2( - Utils.roundSymmetric( vertex.x / epsilon ) * epsilon, - Utils.roundSymmetric( vertex.y / epsilon ) * epsilon + roundSymmetric( vertex.x / epsilon ) * epsilon, + roundSymmetric( vertex.y / epsilon ) * epsilon ); } ) ) ); } @@ -2773,7 +2774,7 @@ export class CircularClipping { assert && assert( a > 0, 'We should have a delta, assumed in code below' ); - const roots = Utils.solveQuadraticRootsReal( a, b, c ); + const roots = solveQuadraticRootsReal( a, b, c ); let isFullyExternal = false; @@ -3140,7 +3141,7 @@ export class CircularClipping { assert && assert( a > 0, 'We should have a delta, assumed in code below' ); - const roots = Utils.solveQuadraticRootsReal( a, b, c ); + const roots = solveQuadraticRootsReal( a, b, c ); let isFullyExternal = false; @@ -3598,7 +3599,7 @@ export class CircularClipping { assert && assert( a > 0, 'We should have a delta, assumed in code below' ); - const roots = Utils.solveQuadraticRootsReal( a, b, c ); + const roots = solveQuadraticRootsReal( a, b, c ); let isFullyExternal = false; diff --git a/js/cag/IntegerEdge.ts b/js/cag/IntegerEdge.ts index df236b7..69b199b 100644 --- a/js/cag/IntegerEdge.ts +++ b/js/cag/IntegerEdge.ts @@ -8,13 +8,13 @@ import Bounds2 from '../../../dot/js/Bounds2.js'; import Matrix3 from '../../../dot/js/Matrix3.js'; -import Utils from '../../../dot/js/Utils.js'; import Vector2 from '../../../dot/js/Vector2.js'; import type { RationalIntersection } from './RationalIntersection.js'; import type { RenderPath } from '../render-program/RenderPath.js'; import type { BoundedSubpath } from './BoundedSubpath.js'; import { BoundsClipping } from '../clip/BoundsClipping.js'; import { alpenglow } from '../alpenglow.js'; +import { roundSymmetric } from '../../../dot/js/util/roundSymmetric.js'; export class IntegerEdge { @@ -74,10 +74,10 @@ export class IntegerEdge { const m10 = toIntegerMatrix.m10(); const m11 = toIntegerMatrix.m11(); const m12 = toIntegerMatrix.m12(); - const x0 = Utils.roundSymmetric( p0.x * m00 + p0.y * m01 + m02 ); - const y0 = Utils.roundSymmetric( p0.x * m10 + p0.y * m11 + m12 ); - const x1 = Utils.roundSymmetric( p1.x * m00 + p1.y * m01 + m02 ); - const y1 = Utils.roundSymmetric( p1.x * m10 + p1.y * m11 + m12 ); + const x0 = roundSymmetric( p0.x * m00 + p0.y * m01 + m02 ); + const y0 = roundSymmetric( p0.x * m10 + p0.y * m11 + m12 ); + const x1 = roundSymmetric( p1.x * m00 + p1.y * m01 + m02 ); + const y1 = roundSymmetric( p1.x * m10 + p1.y * m11 + m12 ); if ( x0 !== x1 || y0 !== y1 ) { return new IntegerEdge( path, x0, y0, x1, y1 ); } diff --git a/js/cag/LinearEdge.ts b/js/cag/LinearEdge.ts index d41be86..5094403 100644 --- a/js/cag/LinearEdge.ts +++ b/js/cag/LinearEdge.ts @@ -7,12 +7,12 @@ */ import Range from '../../../dot/js/Range.js'; -import Utils from '../../../dot/js/Utils.js'; import Vector2 from '../../../dot/js/Vector2.js'; import { Line } from '../../../kite/js/segments/Segment.js'; import Shape from '../../../kite/js/Shape.js'; import { alpenglow } from '../alpenglow.js'; import { ClipSimplifier } from '../clip/ClipSimplifier.js'; +import { arePointsCollinear } from '../../../dot/js/util/arePointsCollinear.js'; export class LinearEdge { @@ -132,8 +132,8 @@ export class LinearEdge { let overlapped = false; for ( const outputEdge of outputEdges ) { // See if the edges are collinear - if ( Utils.arePointsCollinear( edge.startPoint, edge.endPoint, outputEdge.startPoint, epsilon ) && - Utils.arePointsCollinear( edge.startPoint, edge.endPoint, outputEdge.endPoint, epsilon ) ) { + if ( arePointsCollinear( edge.startPoint, edge.endPoint, outputEdge.startPoint, epsilon ) && + arePointsCollinear( edge.startPoint, edge.endPoint, outputEdge.endPoint, epsilon ) ) { const overlaps = Line.getOverlaps( new Line( edge.startPoint, edge.endPoint ), new Line( outputEdge.startPoint, outputEdge.endPoint ), epsilon ); if ( overlaps.length > 0 ) { diff --git a/js/clip/ClipSimplifier.ts b/js/clip/ClipSimplifier.ts index a1658de..e0e021c 100644 --- a/js/clip/ClipSimplifier.ts +++ b/js/clip/ClipSimplifier.ts @@ -15,9 +15,9 @@ */ import Matrix3 from '../../../dot/js/Matrix3.js'; -import Utils from '../../../dot/js/Utils.js'; import Vector2 from '../../../dot/js/Vector2.js'; import { alpenglow } from '../alpenglow.js'; +import { arePointsCollinear } from '../../../dot/js/util/arePointsCollinear.js'; const collinearEpsilon = 1e-9; @@ -60,7 +60,7 @@ export class ClipSimplifier { const secondLastPoint = this.points[ this.points.length - 2 ]; if ( this.checkGeneralCollinearity ) { - if ( Utils.arePointsCollinear( new Vector2( x, y ), lastPoint, secondLastPoint, collinearEpsilon ) ) { + if ( arePointsCollinear( new Vector2( x, y ), lastPoint, secondLastPoint, collinearEpsilon ) ) { lastPoint.x = x; lastPoint.y = y; return; @@ -141,11 +141,11 @@ export class ClipSimplifier { const lastPoint = this.points[ this.points.length - 1 ]; const secondLastPoint = this.points[ this.points.length - 2 ]; - if ( Utils.arePointsCollinear( secondPoint, firstPoint, lastPoint, collinearEpsilon ) ) { + if ( arePointsCollinear( secondPoint, firstPoint, lastPoint, collinearEpsilon ) ) { this.points.shift(); changed = true; } - if ( Utils.arePointsCollinear( firstPoint, lastPoint, secondLastPoint, collinearEpsilon ) ) { + if ( arePointsCollinear( firstPoint, lastPoint, secondLastPoint, collinearEpsilon ) ) { this.points.pop(); changed = true; } diff --git a/js/clip/GridClipping.ts b/js/clip/GridClipping.ts index 00f12ce..d498e4c 100644 --- a/js/clip/GridClipping.ts +++ b/js/clip/GridClipping.ts @@ -6,11 +6,11 @@ * @author Jonathan Olson */ -import Utils from '../../../dot/js/Utils.js'; import { clamp } from '../../../dot/js/util/clamp.js'; import Vector2 from '../../../dot/js/Vector2.js'; import { alpenglow } from '../alpenglow.js'; import { LineClipping } from './LineClipping.js'; +import { roundSymmetric } from '../../../dot/js/util/roundSymmetric.js'; const scratchStartPoint = new Vector2( 0, 0 ); const scratchEndPoint = new Vector2( 0, 0 ); @@ -94,10 +94,10 @@ export class GridClipping { const maxRawStartStepX = Math.max( rawStartStepX, rawEndStepX ); const maxRawStartStepY = Math.max( rawStartStepY, rawEndStepY ); - const roundedMinStepX = Utils.roundSymmetric( minRawStartStepX ); - const roundedMinStepY = Utils.roundSymmetric( minRawStartStepY ); - const roundedMaxStepX = Utils.roundSymmetric( maxRawStartStepX ); - const roundedMaxStepY = Utils.roundSymmetric( maxRawStartStepY ); + const roundedMinStepX = roundSymmetric( minRawStartStepX ); + const roundedMinStepY = roundSymmetric( minRawStartStepY ); + const roundedMaxStepX = roundSymmetric( maxRawStartStepX ); + const roundedMaxStepY = roundSymmetric( maxRawStartStepY ); // Integral "step" coordinates - with slight perturbation to expand our region to cover points/lines that lie // exactly on our grid lines (but not outside of our bounds) @@ -516,10 +516,10 @@ export class GridClipping { const maxRawStartStepX = Math.max( rawStartStepX, rawEndStepX ); const maxRawStartStepY = Math.max( rawStartStepY, rawEndStepY ); - const roundedMinStepX = Utils.roundSymmetric( minRawStartStepX ); - const roundedMinStepY = Utils.roundSymmetric( minRawStartStepY ); - const roundedMaxStepX = Utils.roundSymmetric( maxRawStartStepX ); - const roundedMaxStepY = Utils.roundSymmetric( maxRawStartStepY ); + const roundedMinStepX = roundSymmetric( minRawStartStepX ); + const roundedMinStepY = roundSymmetric( minRawStartStepY ); + const roundedMaxStepX = roundSymmetric( maxRawStartStepX ); + const roundedMaxStepY = roundSymmetric( maxRawStartStepY ); // Integral "step" coordinates - with slight perturbation to expand our region to cover points/lines that lie // exactly on our grid lines (but not outside of our bounds) diff --git a/js/render-program/RenderImage.ts b/js/render-program/RenderImage.ts index 789da12..823b84b 100644 --- a/js/render-program/RenderImage.ts +++ b/js/render-program/RenderImage.ts @@ -7,7 +7,6 @@ */ import Matrix3 from '../../../dot/js/Matrix3.js'; -import Utils from '../../../dot/js/Utils.js'; import Vector2 from '../../../dot/js/Vector2.js'; import Vector4 from '../../../dot/js/Vector4.js'; import { alpenglow } from '../alpenglow.js'; @@ -23,6 +22,7 @@ import type { RenderExecutionStack } from './RenderExecutionStack.js'; import type { RenderExecutor } from './RenderExecutor.js'; import type { ByteEncoder } from '../webgpu/compute/ByteEncoder.js'; import { clamp } from '../../../dot/js/util/clamp.js'; +import { roundSymmetric } from '../../../dot/js/util/roundSymmetric.js'; const emptyChildren: RenderProgram[] = []; @@ -270,7 +270,7 @@ export class RenderImage extends RenderProgram { case RenderExtend.Repeat: return t - Math.floor( t ); case RenderExtend.Reflect: - return Math.abs( t - 2.0 * Utils.roundSymmetric( 0.5 * t ) ); + return Math.abs( t - 2.0 * roundSymmetric( 0.5 * t ) ); // return ( Math.floor( t ) % 2 === 0 ? t : 1 - t ) - Math.floor( t ); default: throw new Error( 'Unknown RenderExtend' ); @@ -394,8 +394,8 @@ export class RenderImageLogic { switch( this.resampleType ) { case RenderResampleType.NearestNeighbor: { const localPoint = this.inverseTransformWithHalfOffset.timesVector2( context.centroid ); - const roundedX = Utils.roundSymmetric( localPoint.x ); - const roundedY = Utils.roundSymmetric( localPoint.y ); + const roundedX = roundSymmetric( localPoint.x ); + const roundedY = roundSymmetric( localPoint.y ); const x = RenderImage.extendInteger( roundedX, this.image.width, this.extendX ); const y = RenderImage.extendInteger( roundedY, this.image.height, this.extendY ); diff --git a/js/webgpu/PerformanceTesting.ts b/js/webgpu/PerformanceTesting.ts index 570ce0e..e6a2152 100644 --- a/js/webgpu/PerformanceTesting.ts +++ b/js/webgpu/PerformanceTesting.ts @@ -6,7 +6,6 @@ * @author Jonathan Olson */ -import Utils from '../../../dot/js/Utils.js'; import { alpenglow } from '../alpenglow.js'; import { DeviceContext } from './compute/DeviceContext.js'; import { getArrayType, U32Order } from './compute/ConcreteType.js'; @@ -15,6 +14,7 @@ import { RadixSortModule } from './modules/gpu/RadixSortModule.js'; import { u32S } from './wgsl/WGSLString.js'; import { Routine } from './compute/Routine.js'; import { Procedure } from './compute/Procedure.js'; +import { toFixed } from '../../../dot/js/util/toFixed.js'; export class PerformanceTesting { public static async loopRadixSortTest( @@ -96,7 +96,7 @@ export class PerformanceTesting { const elapsed = now - startTime; startTime = now; elapsedTimes.push( elapsed ); - console.log( Utils.toFixed( elapsed, 0 ), elapsedTimes.length > 1 ? Utils.toFixed( _.sum( elapsedTimes.slice( 1 ) ) / elapsedTimes.slice( 1 ).length, 0 ) : 0 ); + console.log( toFixed( elapsed, 0 ), elapsedTimes.length > 1 ? toFixed( _.sum( elapsedTimes.slice( 1 ) ) / elapsedTimes.slice( 1 ).length, 0 ) : 0 ); } // TODO: maybe avoid the await on the first frame? diff --git a/js/webgpu/compute/Executor.ts b/js/webgpu/compute/Executor.ts index aecc59b..092e341 100644 --- a/js/webgpu/compute/Executor.ts +++ b/js/webgpu/compute/Executor.ts @@ -6,7 +6,6 @@ * @author Jonathan Olson */ -import Utils from '../../../../dot/js/Utils.js'; import { optionize3 } from '../../../../phet-core/js/optionize.js'; import { alpenglow } from '../../alpenglow.js'; import type { DeviceContext } from './DeviceContext.js'; @@ -15,6 +14,7 @@ import { ComputePass } from './ComputePass.js'; import type { TypedBuffer } from './TypedBuffer.js'; import { webgpu } from '../WebGPUAPI.js'; import { ConsoleLogger } from './ConsoleLogger.js'; +import { roundSymmetric } from '../../../../dot/js/util/roundSymmetric.js'; export type ExecutorOptions = { getTimestampWrites?: ( name: string ) => GPUComputePassTimestampWrites | null; @@ -137,7 +137,7 @@ export class Executor { if ( logResult ) { const data = new Uint32Array( logResult ); const length = data[ 0 ]; - const usedMessage = `logging used ${length} of ${data.length - 1} u32s (${Utils.roundSymmetric( 100 * length / ( data.length - 1 ) )}%)`; + const usedMessage = `logging used ${length} of ${data.length - 1} u32s (${roundSymmetric( 100 * length / ( data.length - 1 ) )}%)`; console.log( usedMessage ); const logData = ConsoleLogger.analyze( logResult ); diff --git a/js/webgpu/compute/TimestampLogger.ts b/js/webgpu/compute/TimestampLogger.ts index 2b62de6..9b19591 100644 --- a/js/webgpu/compute/TimestampLogger.ts +++ b/js/webgpu/compute/TimestampLogger.ts @@ -6,12 +6,12 @@ * @author Jonathan Olson */ -import Utils from '../../../../dot/js/Utils.js'; import { alpenglow } from '../../alpenglow.js'; import type { DeviceContext } from './DeviceContext.js'; import { webgpu } from '../WebGPUAPI.js'; import type { BufferLogger } from './BufferLogger.js'; import { ByteEncoder } from './ByteEncoder.js'; +import { roundSymmetric } from '../../../../dot/js/util/roundSymmetric.js'; export class TimestampLogger { @@ -107,7 +107,7 @@ export class TimestampLoggerResult { public toString(): string { const numToTimestamp = ( n: number ): string => { let result = ''; - let digits = '' + Utils.roundSymmetric( n ); + let digits = '' + roundSymmetric( n ); while ( digits.length ) { if ( digits.length > 3 ) { diff --git a/tests/playground.html b/tests/playground.html index 9720680..e0d8634 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -533,7 +533,7 @@ const point = matrix.inverted().timesVector2( event.pointer.point ); const polygon = [ phet.dot.v2( 48, 48 ), - phet.dot.v2( phet.dot.Utils.clamp( point.x, 0, 100 ), phet.dot.Utils.clamp( point.y, 0, 100 ) ) + phet.dot.v2( phet.dot.clamp( point.x, 0, 100 ), phet.dot.clamp( point.y, 0, 100 ) ) ]; scene.children = [ twoPointsToNode( polygon ) ]; } @@ -743,7 +743,7 @@ const polygon = [ phet.dot.v2( 22, 22 ), phet.dot.v2( 36, 78 ), - phet.dot.v2( phet.dot.Utils.clamp( point.x, 0, 100 ), phet.dot.Utils.clamp( point.y, 0, 100 ) ) + phet.dot.v2( phet.dot.clamp( point.x, 0, 100 ), phet.dot.clamp( point.y, 0, 100 ) ) ]; scene.children = [ polygonToNode( polygon ) ]; } @@ -1713,7 +1713,7 @@ let r0 = fromIntegerPoint( tileLog, p1 ).plus( offset2 ); const r1 = fromIntegerPoint( tileLog, mid2 ).plus( offset2 ); - const intersection = phet.dot.Utils.lineLineIntersection( q0, q1, r0, r1 ); + const intersection = phet.dot.lineLineIntersection( q0, q1, r0, r1 ); if ( intersection !== null ) { q1 = intersection; r0 = intersection; @@ -1796,7 +1796,7 @@ let r0 = p1.plus( offset2 ); const r1 = p2.plus( offset2 ); - const intersection = phet.dot.Utils.lineLineIntersection( q0, q1, r0, r1 ); + const intersection = phet.dot.lineLineIntersection( q0, q1, r0, r1 ); if ( intersection !== null ) { return intersection; }