Skip to content

Commit

Permalink
Merge pull request #4 from shreshthmohan/meta
Browse files Browse the repository at this point in the history
add meta, warnings, errors (0.1.5 → 1.0.0)
  • Loading branch information
shreshthmohan authored Apr 6, 2022
2 parents e21b84c + 0b1d5f3 commit e3dae18
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 20 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# changelog

## Changes in 1.0.0

- Breaking: The return value is now an **object** instead of a **string**
- Added meta information, errors, and warnings
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ const pathStringC = roundedPolygonByCircumRadius({
// set this to the "d" attribute of a <path> SVG element
```

### return value

The return value is an **object** with the following properties:

- `d` (string) SVG path string to be used as a value to the `d` attributes of a `<path>` element
- `meta` (object) contains helpful values: `sideLength`, `circumRadius`, `inRadius`, `minSideLength`, and `borderRadius`
- `warnings` (an array of strings)
- `errors` (an array of strings)

## `roundedPolygonBySideLength(options)`

`options` properties
Expand Down Expand Up @@ -72,6 +81,15 @@ const pathStringS = roundedPolygonBySideLength({
// set this to the "d" attribute of a <path> SVG element
```

### return value

The return value is an **object** with the following properties:

- `d` (string) SVG path string to be used as a value to the `d` attributes of a `<path>` element
- `meta` (object) contains helpful values: `sideLength`, `circumRadius`, `inRadius`, `minSideLength`, and `borderRadius`
- `warnings` (an array of strings)
- `errors` (an array of strings)

## Demos

- [Codepen (UMD)](https://codepen.io/shreshthmohan/pen/mdpqaPY)
Expand Down
22 changes: 14 additions & 8 deletions demo/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { roundedPolygonByCircumRadius } from 'curved-polygon'
import {
roundedPolygonByCircumRadius,
roundedPolygonBySideLength,
} from '../src/index'

const d1 = roundedPolygonByCircumRadius({
circumRadius: 80,
sideCount: 3,
rotate: 0,
cx: 120,
cy: 150,
borderRadius: 10,
borderRadius: 15,
})
const d2 = roundedPolygonByCircumRadius({
circumRadius: 80,
const d2 = roundedPolygonBySideLength({
sideLength: 130,
sideCount: 3,
rotate: 90,
rotate: 30,
cx: 300,
cy: 150,
borderRadius: 10,
borderRadius: -17.5,
})

document.getElementById('polygon1').setAttribute('d', d1)
document.getElementById('polygon2').setAttribute('d', d2)
console.log({ d1 })
console.log({ d2 })

document.getElementById('polygon1').setAttribute('d', d1.d)
document.getElementById('polygon2').setAttribute('d', d2.d)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "curved-polygon",
"version": "0.1.5",
"version": "1.0.0",
"description": "Generate path string for curved polygons in SVG",
"main": "./cjs/index.js",
"scripts": {
Expand Down
155 changes: 144 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ type CartesianPoint = [number, number] // x, y

const PI = Math.PI

interface PolygonData {
d: string
errors?: string[]
meta?: {
inRadius: number
sideLength: number
circumRadius: number
borderRadius: number
minSideLength: number
}
warnings?: string[]
}

function sideLengthFromInRadius({
inRadius,
anglePerSide,
}: {
inRadius: number
anglePerSide: number
}) {
const sideLength = inRadius * 2 * Math.tan(anglePerSide / 2)
return sideLength
}

// returns the d attribute used for SVG <path> element
export function roundedPolygonBySideLength({
sideLength,
Expand All @@ -19,9 +43,44 @@ export function roundedPolygonBySideLength({
cx?: number
cy?: number
rotate?: number
}): string {
const { circumcircleRadius: r, angleIntendedBySide: alpha } =
polygonSideToCircleRadius({ sideLength, sideCount })
}): PolygonData {
const errors = []
const warnings = []

if (sideCount < 3) {
errors.push(
'sideCount cannot be smaller than 3. There is no polygon with fewer sides than a triangle. No fun shapes here. :) Sorry!',
)
}
if (errors.length) {
return { d: '', errors }
}

const {
circumRadius: r,
angleIntendedBySide: alpha,
inRadius,
} = polygonSidetoCircumRadius({ sideLength, sideCount })

const minSideLength = sideLengthFromInRadius({
inRadius: borderRadius,
anglePerSide: alpha,
})

if (borderRadius > inRadius) {
warnings.push(
`borderRadius(${borderRadius}) is larger than inradius(${inRadius}) of the polygon. The resulting shape won't really be a polygon.
To get a proper curved polygon, either make the border radius smaller than ${inRadius} or make the sideLength larger than ${minSideLength}.
Ignore this warning if you intentionally want this curious pattern.
`,
)
}

if (borderRadius < 0) {
warnings.push(
'You provided a negative borderRadius. Might produce an unexpected shape that is not a polygon. Ignore this warning if this was intentional.',
)
}

// polygon on which the centres of border circles lie
const radiusOfInnerPolygon = r - borderRadius / Math.cos(alpha / 2)
Expand All @@ -40,7 +99,17 @@ export function roundedPolygonBySideLength({
})

const dForPath: string = pointsToDForPath({ allPoints, borderRadius, alpha })
return dForPath
return {
d: dForPath,
meta: {
circumRadius: r,
inRadius,
sideLength,
borderRadius,
minSideLength,
},
warnings,
}
}

export function roundedPolygonByCircumRadius({
Expand All @@ -58,7 +127,45 @@ export function roundedPolygonByCircumRadius({
cy?: number
rotate?: number
}) {
const alpha = angleIntendedByPolygonSide(sideCount) // in radians
const errors = []
const warnings = []

if (sideCount < 3) {
errors.push(
'sideCount cannot be smaller than 3. There is no polygon with fewer sides than a triangle. No fun shapes here. :) Sorry!',
)
}

if (errors.length) {
return { d: '', errors }
}
const {
sideLength,
inRadius,
angleIntendedBySide: alpha,
} = circumRadiusToPolygonSide({
sideCount,
circumRadius,
})

const minSideLength = sideLengthFromInRadius({
inRadius: borderRadius,
anglePerSide: alpha,
})
if (borderRadius > inRadius) {
warnings.push(
`borderRadius(${borderRadius}) is larger than inradius(${inRadius}) of the polygon. The resulting shape won't really be a polygon.
To get a proper curved polygon, either make the border radius smaller than ${inRadius} or make the sideLength larger than ${minSideLength}.
Ignore this warning if you intentionally want this curious pattern.
`,
)
}

if (borderRadius < 0) {
warnings.push(
'You provided a negative borderRadius. Might produce an unexpected shape that is not a polygon. Ignore this warning if this was intentional.',
)
}

const radiusOfInnerPolygon = circumRadius - borderRadius / Math.cos(alpha / 2)

Expand All @@ -76,7 +183,17 @@ export function roundedPolygonByCircumRadius({
})

const dForPath: string = pointsToDForPath({ allPoints, borderRadius, alpha })
return dForPath
return {
d: dForPath,
meta: {
circumRadius,
inRadius,
sideLength,
borderRadius,
minSideLength,
},
warnings,
}
}

// returns d attribute used in the SVG <path> element
Expand Down Expand Up @@ -147,22 +264,38 @@ function angleIntendedByPolygonSide(sideCount: number): number {
return (2 * PI) / sideCount
}

function polygonSideToCircleRadius({
function polygonSidetoCircumRadius({
sideLength,
sideCount,
}: {
sideLength: number
sideCount: number
}): { circumcircleRadius: number; angleIntendedBySide: number } {
}): { circumRadius: number; angleIntendedBySide: number; inRadius: number } {
// angle intended by side of polygon onto the circumscribed circle
// unit: radians
// alias: alpha
const angleIntendedBySide = angleIntendedByPolygonSide(sideCount)

const circumcircleRadius =
sideLength / (2 * Math.sin(angleIntendedBySide / 2))
const circumRadius = sideLength / (2 * Math.sin(angleIntendedBySide / 2))

const inRadius = sideLength / (2 * Math.tan(angleIntendedBySide / 2))

return { circumRadius, angleIntendedBySide, inRadius }
}

function circumRadiusToPolygonSide({
circumRadius,
sideCount,
}: {
circumRadius: number
sideCount: number
}): { sideLength: number; angleIntendedBySide: number; inRadius: number } {
const angleIntendedBySide = angleIntendedByPolygonSide(sideCount)

const sideLength = circumRadius * (2 * Math.sin(angleIntendedBySide / 2))

return { circumcircleRadius, angleIntendedBySide }
const inRadius = sideLength / (2 * Math.tan(angleIntendedBySide / 2))
return { sideLength, angleIntendedBySide, inRadius }
}

// Did not keep it in polar, because the calculation gets complicated
Expand Down

0 comments on commit e3dae18

Please sign in to comment.