Commands/Custom/SVG.CurvePath.ps.ps1

function SVG.CurvePath
{
    <#
    .SYNOPSIS
        Draws an SVG curve.
    .DESCRIPTION
        Draws an SVG curve path.
    .EXAMPLE
        =<svg> -OutputPath .\Curves.svg @(
            =<svg.CurvePath> -Start 10 -ControlPoint 15,5,20,40 -End 30,30 -fill transparent -stroke black
        ) -viewbox 50, 50
    .LINK
        SVG.Path
    #>
    
    [inherit('SVG.path', Dynamic, Abstract)]
    [Alias('SVG.CurvedPath','=<SVG.CurvedPath>')]
    param(
    # One or two control points.
    # If two control points are provided, it will be assumed to be a Bezier curve.
    # If only one control point is provided, it will be assumed to be a Quadratic curve.
    [Parameter(ValueFromPipelineByPropertyName)]
    [double[]]
    $ControlPoint,

    # The start point of the curve.
    # If only one value is provided, it will be used as the X and Y coordinate.
    [Parameter(ValueFromPipelineByPropertyName)]
    [double[]]
    $Start,

    # The end point of the curve.
    # If only one value is provided, it will be used as the X and Y coordinate.
    [Parameter(ValueFromPipelineByPropertyName)]
    [double[]]
    $End,

    # If set, will attempt to draw a smooth bezier curve.
    [Parameter(ValueFromPipelineByPropertyName)]
    [switch]
    $Smooth,

    # If set, will draw a multi-quadratic line.
    # This can only be used if preceeded by another curve.
    [Parameter(ValueFromPipelineByPropertyName)]
    [switch]
    $MultiQuadratic,

    # If set, will draw a quadratic bezier curve.
    # This is the default, as it only requires a single control point.
    [Parameter(ValueFromPipelineByPropertyName)]
    [switch]
    $Quadratic,

    # If set, will close the path after this element.
    [Parameter(ValueFromPipelineByPropertyName)]
    [switch]
    $Close
    )

    process {
        $existingPath = ''
        if ($PSBoundParameters.D) {
            $existingPath = $PSBoundParameters.D + ' '
        }

        if ($_ -eq $PSBoundParameters.Content) {
            $null = $PSBoundParameters.Remove('Content')
        }
        
        if ($ControlPoint.Length -eq 1) {
            $ControlPoint = $ControlPoint[0], $ControlPoint[0]
        }

        if ($ControlPoint.Length -gt 4) {
            Write-Error "Up to two control points can be provided"
            return
        }

        $arcPath = @(
            if ($psBoundParameters.Keys -eq 'Start') {
                "M"
                if ($start.Length -gt 2) {
                    Write-Error "-Start can only contain one or two values"
                    return
                }
                elseif ($start.Length -eq 2) {
                    $start[0],$start[1]
                }
                else {
                    $start[0],$start[0]
                }
            }        
            if ($ControlPoint.Length -ge 4) {
                "C" # Bezier curves have 2 control points
            } else {
                if ($Smooth) {
                    "S"
                }
                elseif ($MultiQuadratic) {
                    "T"
                } else{
                    "Q"
                }
            }
            
            for ($cpIndex =0 ; $cpIndex -lt $ControlPoint.Length; $cpIndex+=2 ) {
                $ControlPoint[$cpIndex]
                $ControlPoint[$cpIndex + 1]
                ","
            }            
            if ($end.Length -gt 2) {
                Write-Error "-End can only contain one or two values."
                return
            }
            elseif ($end.Length -eq 2 ) {
                $End[0],$end[1]
            } elseif ($end.Length -eq 1) {
                $End[0],$end[0]
            } else {
                0, 0
            }
            
            if ($Close) {
                "Z"
            }
        ) -join ' '
        
        $PSBoundParameters['D'] = $existingPath + $arcPath
        $baseSplat = [Ordered]@{}
        foreach ($k in $PSBoundParameters.Keys) {
            if ($baseCommand.Parameters[$k]) {
                $baseSplat[$k]  = $PSBoundParameters[$k]
            }
        }
        
        SVG.Path @baseSplat
    }
}