@tldraw/editor 3.15.0-canary.84e5eaec2c02 → 3.15.0-canary.8789e24bb6fc

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.
Files changed (106) hide show
  1. package/dist-cjs/index.d.ts +10 -5
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/components/SVGContainer.js +1 -1
  5. package/dist-cjs/lib/components/SVGContainer.js.map +2 -2
  6. package/dist-cjs/lib/components/default-components/DefaultBrush.js +1 -1
  7. package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultGrid.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
  17. package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
  19. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  20. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +1 -1
  21. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
  22. package/dist-cjs/lib/editor/Editor.js +24 -8
  23. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +96 -101
  25. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  26. package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
  27. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  28. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
  29. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  30. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +3 -1
  31. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  32. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
  33. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  34. package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
  35. package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
  36. package/dist-cjs/lib/primitives/intersect.js +4 -4
  37. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  38. package/dist-cjs/lib/primitives/utils.js +4 -0
  39. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  40. package/dist-cjs/version.js +3 -3
  41. package/dist-cjs/version.js.map +1 -1
  42. package/dist-esm/index.d.mts +10 -5
  43. package/dist-esm/index.mjs +3 -1
  44. package/dist-esm/index.mjs.map +2 -2
  45. package/dist-esm/lib/components/SVGContainer.mjs +1 -1
  46. package/dist-esm/lib/components/SVGContainer.mjs.map +2 -2
  47. package/dist-esm/lib/components/default-components/DefaultBrush.mjs +1 -1
  48. package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
  49. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  50. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  51. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  52. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
  53. package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
  54. package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
  55. package/dist-esm/lib/components/default-components/DefaultGrid.mjs +1 -1
  56. package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
  57. package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
  58. package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +2 -2
  59. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
  60. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  61. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +1 -1
  62. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
  63. package/dist-esm/lib/editor/Editor.mjs +24 -8
  64. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  65. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +96 -101
  66. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  67. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  68. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  69. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
  70. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  71. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +3 -1
  72. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  73. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
  74. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  75. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
  76. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
  77. package/dist-esm/lib/primitives/intersect.mjs +5 -5
  78. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  79. package/dist-esm/lib/primitives/utils.mjs +4 -0
  80. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  81. package/dist-esm/version.mjs +3 -3
  82. package/dist-esm/version.mjs.map +1 -1
  83. package/editor.css +2 -2
  84. package/package.json +9 -8
  85. package/src/index.ts +1 -0
  86. package/src/lib/components/SVGContainer.tsx +1 -1
  87. package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
  88. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  89. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  90. package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
  91. package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
  92. package/src/lib/components/default-components/DefaultHandles.tsx +5 -1
  93. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +1 -1
  94. package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
  95. package/src/lib/editor/Editor.test.ts +407 -0
  96. package/src/lib/editor/Editor.ts +35 -9
  97. package/src/lib/editor/managers/TextManager/TextManager.ts +108 -128
  98. package/src/lib/primitives/geometry/Arc2d.ts +2 -2
  99. package/src/lib/primitives/geometry/Circle2d.ts +2 -2
  100. package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -1
  101. package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
  102. package/src/lib/primitives/geometry/geometry-constants.ts +2 -1
  103. package/src/lib/primitives/intersect.test.ts +946 -0
  104. package/src/lib/primitives/intersect.ts +12 -5
  105. package/src/lib/primitives/utils.ts +11 -0
  106. package/src/version.ts +3 -3
@@ -1,4 +1,5 @@
1
1
  import { BoxModel, TLDefaultHorizontalAlignStyle } from '@tldraw/tlschema'
2
+ import { objectMapKeys } from '@tldraw/utils'
2
3
  import { Editor } from '../../Editor'
3
4
 
4
5
  const fixNewLines = /\r?\n|\r/g
@@ -60,10 +61,18 @@ export interface TLMeasureTextSpanOpts {
60
61
 
61
62
  const spaceCharacterRegex = /\s/
62
63
 
64
+ const initialDefaultStyles = Object.freeze({
65
+ 'overflow-wrap': 'break-word',
66
+ 'word-break': 'auto',
67
+ width: null,
68
+ height: null,
69
+ 'max-width': null,
70
+ 'min-width': null,
71
+ })
72
+
63
73
  /** @public */
64
74
  export class TextManager {
65
75
  private elm: HTMLDivElement
66
- private defaultStyles: Record<string, string | null>
67
76
 
68
77
  constructor(public editor: Editor) {
69
78
  const elm = document.createElement('div')
@@ -73,31 +82,34 @@ export class TextManager {
73
82
  elm.tabIndex = -1
74
83
  this.editor.getContainer().appendChild(elm)
75
84
 
76
- // we need to save the default styles so that we can restore them when we're done
77
- // these must be the css names, not the js names for the styles
78
- this.defaultStyles = {
79
- 'overflow-wrap': 'break-word',
80
- 'word-break': 'auto',
81
- width: null,
82
- height: null,
83
- 'max-width': null,
84
- 'min-width': null,
85
+ this.elm = elm
86
+
87
+ for (const key of objectMapKeys(initialDefaultStyles)) {
88
+ elm.style.setProperty(key, initialDefaultStyles[key])
85
89
  }
90
+ }
86
91
 
87
- this.elm = elm
92
+ private setElementStyles(styles: Record<string, string | undefined>) {
93
+ const stylesToReinstate = {} as any
94
+ for (const key of objectMapKeys(styles)) {
95
+ if (typeof styles[key] === 'string') {
96
+ const oldValue = this.elm.style.getPropertyValue(key)
97
+ if (oldValue === styles[key]) continue
98
+ stylesToReinstate[key] = oldValue
99
+ this.elm.style.setProperty(key, styles[key])
100
+ }
101
+ }
102
+ return () => {
103
+ for (const key of objectMapKeys(stylesToReinstate)) {
104
+ this.elm.style.setProperty(key, stylesToReinstate[key])
105
+ }
106
+ }
88
107
  }
89
108
 
90
109
  dispose() {
91
110
  return this.elm.remove()
92
111
  }
93
112
 
94
- private resetElmStyles() {
95
- const { elm, defaultStyles } = this
96
- for (const key in defaultStyles) {
97
- elm.style.setProperty(key, defaultStyles[key])
98
- }
99
- }
100
-
101
113
  measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
102
114
  const div = document.createElement('div')
103
115
  div.textContent = normalizeTextForDom(textToMeasure)
@@ -107,54 +119,36 @@ export class TextManager {
107
119
  measureHtml(html: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
108
120
  const { elm } = this
109
121
 
110
- if (opts.otherStyles) {
111
- for (const key in opts.otherStyles) {
112
- if (!this.defaultStyles[key]) {
113
- // we need to save the original style so that we can restore it when we're done
114
- this.defaultStyles[key] = elm.style.getPropertyValue(key)
115
- }
116
- }
122
+ const newStyles = {
123
+ 'font-family': opts.fontFamily,
124
+ 'font-style': opts.fontStyle,
125
+ 'font-weight': opts.fontWeight,
126
+ 'font-size': opts.fontSize + 'px',
127
+ 'line-height': opts.lineHeight.toString(),
128
+ padding: opts.padding,
129
+ 'max-width': opts.maxWidth ? opts.maxWidth + 'px' : undefined,
130
+ 'min-width': opts.minWidth ? opts.minWidth + 'px' : undefined,
131
+ 'overflow-wrap': opts.disableOverflowWrapBreaking ? 'normal' : undefined,
132
+ ...opts.otherStyles,
117
133
  }
118
134
 
119
- elm.innerHTML = html
135
+ const restoreStyles = this.setElementStyles(newStyles)
120
136
 
121
- // Apply the default styles to the element (for all styles here or that were ever seen in opts.otherStyles)
122
- this.resetElmStyles()
137
+ try {
138
+ elm.innerHTML = html
123
139
 
124
- elm.style.setProperty('font-family', opts.fontFamily)
125
- elm.style.setProperty('font-style', opts.fontStyle)
126
- elm.style.setProperty('font-weight', opts.fontWeight)
127
- elm.style.setProperty('font-size', opts.fontSize + 'px')
128
- elm.style.setProperty('line-height', opts.lineHeight.toString())
129
- elm.style.setProperty('padding', opts.padding)
140
+ const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
141
+ const rect = elm.getBoundingClientRect()
130
142
 
131
- if (opts.maxWidth) {
132
- elm.style.setProperty('max-width', opts.maxWidth + 'px')
133
- }
134
-
135
- if (opts.minWidth) {
136
- elm.style.setProperty('min-width', opts.minWidth + 'px')
137
- }
138
-
139
- if (opts.disableOverflowWrapBreaking) {
140
- elm.style.setProperty('overflow-wrap', 'normal')
141
- }
142
-
143
- if (opts.otherStyles) {
144
- for (const [key, value] of Object.entries(opts.otherStyles)) {
145
- elm.style.setProperty(key, value)
143
+ return {
144
+ x: 0,
145
+ y: 0,
146
+ w: rect.width,
147
+ h: rect.height,
148
+ scrollWidth,
146
149
  }
147
- }
148
-
149
- const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
150
- const rect = elm.getBoundingClientRect()
151
-
152
- return {
153
- x: 0,
154
- y: 0,
155
- w: rect.width,
156
- h: rect.height,
157
- scrollWidth,
150
+ } finally {
151
+ restoreStyles()
158
152
  }
159
153
  }
160
154
 
@@ -274,82 +268,68 @@ export class TextManager {
274
268
 
275
269
  const { elm } = this
276
270
 
277
- if (opts.otherStyles) {
278
- for (const key in opts.otherStyles) {
279
- if (!this.defaultStyles[key]) {
280
- // we need to save the original style so that we can restore it when we're done
281
- this.defaultStyles[key] = elm.style.getPropertyValue(key)
282
- }
283
- }
284
- }
285
-
286
- this.resetElmStyles()
287
-
288
- elm.style.setProperty('font-family', opts.fontFamily)
289
- elm.style.setProperty('font-style', opts.fontStyle)
290
- elm.style.setProperty('font-weight', opts.fontWeight)
291
- elm.style.setProperty('font-size', opts.fontSize + 'px')
292
- elm.style.setProperty('line-height', opts.lineHeight.toString())
293
-
294
- const elementWidth = Math.ceil(opts.width - opts.padding * 2)
295
- elm.style.setProperty('width', `${elementWidth}px`)
296
- elm.style.setProperty('height', 'min-content')
297
- elm.style.setProperty('text-align', textAlignmentsForLtr[opts.textAlign])
298
-
299
271
  const shouldTruncateToFirstLine =
300
272
  opts.overflow === 'truncate-ellipsis' || opts.overflow === 'truncate-clip'
301
-
302
- if (shouldTruncateToFirstLine) {
303
- elm.style.setProperty('overflow-wrap', 'anywhere')
304
- elm.style.setProperty('word-break', 'break-all')
305
- }
306
-
307
- if (opts.otherStyles) {
308
- for (const [key, value] of Object.entries(opts.otherStyles)) {
309
- elm.style.setProperty(key, value)
310
- }
273
+ const elementWidth = Math.ceil(opts.width - opts.padding * 2)
274
+ const newStyles = {
275
+ 'font-family': opts.fontFamily,
276
+ 'font-style': opts.fontStyle,
277
+ 'font-weight': opts.fontWeight,
278
+ 'font-size': opts.fontSize + 'px',
279
+ 'line-height': opts.lineHeight.toString(),
280
+ width: `${elementWidth}px`,
281
+ height: 'min-content',
282
+ 'text-align': textAlignmentsForLtr[opts.textAlign],
283
+ 'overflow-wrap': shouldTruncateToFirstLine ? 'anywhere' : undefined,
284
+ 'word-break': shouldTruncateToFirstLine ? 'break-all' : undefined,
285
+ ...opts.otherStyles,
311
286
  }
287
+ const restoreStyles = this.setElementStyles(newStyles)
312
288
 
313
- const normalizedText = normalizeTextForDom(textToMeasure)
314
-
315
- // Render the text into the measurement element:
316
- elm.textContent = normalizedText
317
-
318
- // actually measure the text:
319
- const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
320
- shouldTruncateToFirstLine,
321
- })
289
+ try {
290
+ const normalizedText = normalizeTextForDom(textToMeasure)
322
291
 
323
- if (opts.overflow === 'truncate-ellipsis' && didTruncate) {
324
- // we need to measure the ellipsis to know how much space it takes up
325
- elm.textContent = '…'
326
- const ellipsisWidth = Math.ceil(this.measureElementTextNodeSpans(elm).spans[0].box.w)
327
-
328
- // then, we need to subtract that space from the width we have and measure again:
329
- elm.style.setProperty('width', `${elementWidth - ellipsisWidth}px`)
292
+ // Render the text into the measurement element:
330
293
  elm.textContent = normalizedText
331
- const truncatedSpans = this.measureElementTextNodeSpans(elm, {
332
- shouldTruncateToFirstLine: true,
333
- }).spans
334
-
335
- // Finally, we add in our ellipsis at the end of the last span. We
336
- // have to do this after measuring, not before, because adding the
337
- // ellipsis changes how whitespace might be getting collapsed by the
338
- // browser.
339
- const lastSpan = truncatedSpans[truncatedSpans.length - 1]!
340
- truncatedSpans.push({
341
- text: '…',
342
- box: {
343
- x: Math.min(lastSpan.box.x + lastSpan.box.w, opts.width - opts.padding - ellipsisWidth),
344
- y: lastSpan.box.y,
345
- w: ellipsisWidth,
346
- h: lastSpan.box.h,
347
- },
294
+
295
+ // actually measure the text:
296
+ const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
297
+ shouldTruncateToFirstLine,
348
298
  })
349
299
 
350
- return truncatedSpans
351
- }
300
+ if (opts.overflow === 'truncate-ellipsis' && didTruncate) {
301
+ // we need to measure the ellipsis to know how much space it takes up
302
+ elm.textContent = '…'
303
+ const ellipsisWidth = Math.ceil(this.measureElementTextNodeSpans(elm).spans[0].box.w)
304
+
305
+ // then, we need to subtract that space from the width we have and measure again:
306
+ elm.style.setProperty('width', `${elementWidth - ellipsisWidth}px`)
307
+ elm.textContent = normalizedText
308
+ const truncatedSpans = this.measureElementTextNodeSpans(elm, {
309
+ shouldTruncateToFirstLine: true,
310
+ }).spans
311
+
312
+ // Finally, we add in our ellipsis at the end of the last span. We
313
+ // have to do this after measuring, not before, because adding the
314
+ // ellipsis changes how whitespace might be getting collapsed by the
315
+ // browser.
316
+ const lastSpan = truncatedSpans[truncatedSpans.length - 1]!
317
+ truncatedSpans.push({
318
+ text: '…',
319
+ box: {
320
+ x: Math.min(lastSpan.box.x + lastSpan.box.w, opts.width - opts.padding - ellipsisWidth),
321
+ y: lastSpan.box.y,
322
+ w: ellipsisWidth,
323
+ h: lastSpan.box.h,
324
+ },
325
+ })
326
+
327
+ return truncatedSpans
328
+ }
352
329
 
353
- return spans
330
+ return spans
331
+ } finally {
332
+ restoreStyles()
333
+ }
354
334
  }
355
335
  }
@@ -2,7 +2,7 @@ import { Vec, VecLike } from '../Vec'
2
2
  import { intersectLineSegmentCircle } from '../intersect'
3
3
  import { getArcMeasure, getPointInArcT, getPointOnCircle } from '../utils'
4
4
  import { Geometry2d, Geometry2dOptions } from './Geometry2d'
5
- import { getVerticesCountForLength } from './geometry-constants'
5
+ import { getVerticesCountForArcLength } from './geometry-constants'
6
6
 
7
7
  /** @public */
8
8
  export class Arc2d extends Geometry2d {
@@ -94,7 +94,7 @@ export class Arc2d extends Geometry2d {
94
94
  getVertices(): Vec[] {
95
95
  const { _center, _measure: measure, length, _radius: radius, _angleStart: angleStart } = this
96
96
  const vertices: Vec[] = []
97
- for (let i = 0, n = getVerticesCountForLength(Math.abs(length)); i < n + 1; i++) {
97
+ for (let i = 0, n = getVerticesCountForArcLength(Math.abs(length)); i < n + 1; i++) {
98
98
  const t = (i / n) * measure
99
99
  const angle = angleStart + t
100
100
  vertices.push(getPointOnCircle(_center, radius, angle))
@@ -3,7 +3,7 @@ import { Vec, VecLike } from '../Vec'
3
3
  import { intersectLineSegmentCircle } from '../intersect'
4
4
  import { PI2, getPointOnCircle } from '../utils'
5
5
  import { Geometry2d, Geometry2dOptions } from './Geometry2d'
6
- import { getVerticesCountForLength } from './geometry-constants'
6
+ import { getVerticesCountForArcLength } from './geometry-constants'
7
7
 
8
8
  /** @public */
9
9
  export class Circle2d extends Geometry2d {
@@ -36,7 +36,7 @@ export class Circle2d extends Geometry2d {
36
36
  const { _center, _radius: radius } = this
37
37
  const perimeter = PI2 * radius
38
38
  const vertices: Vec[] = []
39
- for (let i = 0, n = getVerticesCountForLength(perimeter); i < n; i++) {
39
+ for (let i = 0, n = getVerticesCountForArcLength(perimeter); i < n; i++) {
40
40
  const angle = (i / n) * PI2
41
41
  vertices.push(getPointOnCircle(_center, radius, angle))
42
42
  }
@@ -8,6 +8,7 @@ export class CubicBezier2d extends Polyline2d {
8
8
  private _b: Vec
9
9
  private _c: Vec
10
10
  private _d: Vec
11
+ private _resolution: number
11
12
 
12
13
  constructor(
13
14
  config: Omit<Geometry2dOptions, 'isFilled' | 'isClosed'> & {
@@ -15,6 +16,7 @@ export class CubicBezier2d extends Polyline2d {
15
16
  cp1: Vec
16
17
  cp2: Vec
17
18
  end: Vec
19
+ resolution?: number
18
20
  }
19
21
  ) {
20
22
  const { start: a, cp1: b, cp2: c, end: d } = config
@@ -24,13 +26,14 @@ export class CubicBezier2d extends Polyline2d {
24
26
  this._b = b
25
27
  this._c = c
26
28
  this._d = d
29
+ this._resolution = config.resolution ?? 10
27
30
  }
28
31
 
29
32
  override getVertices() {
30
33
  const vertices = [] as Vec[]
31
34
  const { _a: a, _b: b, _c: c, _d: d } = this
32
35
  // we'll always use ten vertices for each bezier curve
33
- for (let i = 0, n = 10; i <= n; i++) {
36
+ for (let i = 0, n = this._resolution; i <= n; i++) {
34
37
  const t = i / n
35
38
  vertices.push(
36
39
  new Vec(
@@ -3,7 +3,7 @@ import { Vec, VecLike } from '../Vec'
3
3
  import { PI, PI2, clamp, perimeterOfEllipse } from '../utils'
4
4
  import { Edge2d } from './Edge2d'
5
5
  import { Geometry2d, Geometry2dOptions } from './Geometry2d'
6
- import { getVerticesCountForLength } from './geometry-constants'
6
+ import { getVerticesCountForArcLength } from './geometry-constants'
7
7
 
8
8
  /** @public */
9
9
  export class Ellipse2d extends Geometry2d {
@@ -47,7 +47,7 @@ export class Ellipse2d extends Geometry2d {
47
47
  const q = Math.pow(cx - cy, 2) / Math.pow(cx + cy, 2)
48
48
  const p = PI * (cx + cy) * (1 + (3 * q) / (10 + Math.sqrt(4 - 3 * q)))
49
49
  // Number of points
50
- const len = getVerticesCountForLength(p)
50
+ const len = getVerticesCountForArcLength(p)
51
51
  // Size of step
52
52
  const step = PI2 / len
53
53
 
@@ -1,6 +1,7 @@
1
1
  const SPACING = 20
2
2
  const MIN_COUNT = 8
3
3
 
4
- export function getVerticesCountForLength(length: number, spacing = SPACING) {
4
+ /** @internal */
5
+ export function getVerticesCountForArcLength(length: number, spacing = SPACING) {
5
6
  return Math.max(MIN_COUNT, Math.ceil(length / spacing))
6
7
  }