EllipseArc

Overview

Class

A segment of an ellipse.

Supertypes

Attributes (data)

Name

Multiplicity

Type

Center

1

Point

EndAngle

1

Double

HorizontalSemiAxis

1

Double

Rotation

1

Double

StartAngle

1

Double

Stroke

1

Stroke

VerticalSemiAxis

1

Double

Geometry

An EllipseArc is a segment of an ellipse. The geometry of the underlying ellipse is described in the same way as the geometry of the actual Ellipse class (Center, HorizontalSemiAxis, VerticalSemiAxis, Rotation). In addition, an EllipseArc has two attributes StartAngle and EndAngle that determine the start and end position of the arc.

Example

We consider an EllipseArc with

These attributes describe the blue dashed ellipse in this figure (cf. the Ellipse example which has the same attribute values).

The EllipseArc has two further geometric attributes

These two angles do not have a simple geometric interpretation in the figure; we will get back to them in the following sections. However, these angles determine the start position and the end position of the black EllipseArc in the figure. The actual EllipseArc goes runs from the start position in positive direction (i.e., clockwise) to the end position.

Calculation of start and end position

We use the following notation:

Technical Note

The notation is based on that used by the SVG Arc Implementation Nodes which may be useful for implementors.

The start position is

\[\begin{split}\left(\begin{array}{c} x_1 \\ y_1 \end{array}\right) = \left(\begin{array}{cc} \cos \varphi & -\sin \varphi \\ \sin \varphi & \cos \varphi \end{array}\right) ⋅ \left(\begin{array}{c} r_x \cos \theta_1 \\ r_y \sin \theta_1 \end{array}\right) + \left(\begin{array}{c} c_x \\ c_y \end{array}\right)\end{split}\]

and the end position is

\[\begin{split}\left(\begin{array}{c} x_2 \\ y_2 \end{array}\right) = \left(\begin{array}{cc} \cos \varphi & -\sin \varphi \\ \sin \varphi & \cos \varphi \end{array}\right) ⋅ \left(\begin{array}{c} r_x \cos \theta_2 \\ r_y \sin \theta_2 \end{array}\right) + \left(\begin{array}{c} c_x \\ c_y \end{array}\right) \quad .\end{split}\]

Example

In the example, we have

\[ \begin{align}\begin{aligned}c_x &= 10\\c_y &= 20\\r_x &= 110\\r_y &= 50\\\varphi &= 35\\\theta_1 &= 288\\\theta_2 &= 20\end{aligned}\end{align} \]

With the equations above, we get these coordinates for the start and end positions (cf. the figure above):

\[ \begin{align}\begin{aligned}x_1 = 65.1197\\y_1 = 0.5439\\x_2 = 84.8639\\y_2 = 93.2967\end{aligned}\end{align} \]

Interpretation of StartAngle and EndAngle

These angles are not measured in the ellipse on which an EllipseArc is based, but in the unit circle:

The figure shows the end position w.r.t. the unit circle. Its angle measured from the horizonal semi-axis is \(\theta_2 = 20\). The ellipse could be constructed by stretching the unit circle by \(r_x\) in direction of the horizontal semi-axis and by \(r_y\) in direction of the vertical semi-axis. After this transformation, the end position w.r.t. the unit circle is at the actual end position.

To calculate an actual, ellipse-based angle from an angle w.r.t. the unit circle, use the formula

\[\theta_{actual} = \textrm{atan2}( r_y \sin \theta, r_x \cos \theta ) \,\textrm{mod}\, 360 \quad.\]

The formulas apply to both the StartAngle \(\theta_1\) and the EndAngle \(\theta_2\). Note that we give angles in degrees, i.e., the actual calculations in a program may require conversions to and from radians.

Example

In the example, we have

\[\theta_{actual, 1} = \textrm{atan2}( 50 ⋅ \sin 288, 110 ⋅ \cos 288) \,\textrm{mod}\, 360 = 305.56\]

and

\[\theta_{actual, 2} = \textrm{atan2}( 50 ⋅ \sin 20, 110 ⋅ \cos 20) \,\textrm{mod}\, 360 = 9.39 \quad .\]

The inverse formula is

\[\theta = \textrm{atan2}( r_x \sin \theta_{actual}, r_y \cos \theta_{actual} ) \,\textrm{mod}\, 360 \quad .\]

Technical Note

The rationale for using angles w.r.t. the unit circle is that they are numerically more stable when an EllipseArc is scaled with small values (i.e., in a ShapeUsage) and that some calculations are simpler (cf. SVG 2 Arc Implementation Nodes).

Mapping to SVG

An EllipseArc is mapped to an svg:path with these attributes:

  • d is the path data that describes the entire geometry of the EllipseArc. The value is the concatenation of the following strings, all of them separated by spaces:

    • M

    • str(\(x_1\))

    • str(\(y_1\))

    • A

    • str(\(r_x\))

    • str(\(r_y\))

    • str(\(\varphi\))

    • str(\(f_A\))

    • 1

    • str(\(x_2\))

    • str(\(y_2\))

    \(f_A\) is calculated as follows (cf. the definition of the modulo operator):

    \[ \begin{align}\begin{aligned}\Delta \theta = (\theta_2 - \theta_1)\, \textrm{mod}\, 360 \quad ,\\\begin{split}f_A = \left\{\begin{array}{cl} 0 & \textrm{if}\, \Delta \theta < 180, \\ 1 & \textrm{otherwise}. \end{array}\right.\end{split}\end{aligned}\end{align} \]

    The other variables have been defined above.

  • stroke, stroke-dasharray, stroke-dashoffset and stroke-width are set according to the SVG mapping rules for the Stroke of the EllipseArc (see Stroke).

  • stroke-linecap = "round" and stroke-linejoin = "round" reflect the heuristic for line caps and line joins.

  • vector-effect = "non-scaling-stroke" reflects the heuristic for scaled symbols.

  • fill = "none" is required to avoid that the svg:path is filled.

Implementation in Proteus Schema

An EllipseArc is implemented using the Proteus elements <TrimmedCurve> and <Ellipse>.

An EllipseArc whose HorizontalSemiAxis equals its VerticalSemiAxis may alternatively be implemented using the Proteus elements <TrimmedCurve> and <Circle>.

Note that Proteus uses the actual start and end angles with respect to the underlying ellipse; the conversion formulas are given above.

Further, the orientation of angles in Proteus is anti-clockwise. Thus, the angles must be converted accordingly, and the start and end angle must be switched.

Example

We assume that the Stroke of the EllipseArc above is 2mm #ff0000 solid.

With \(\Delta \theta = (20 - 288)\, \textrm{mod}\,360 = (-268)\, \textrm{mod}\, 360 = 92 < 180\) we get \(f_A = 0\).

<svg
  xmlns = "http://www.w3.org/2000/svg"
  width = "42mm"
  height = "96mm"
  viewBox = "64 -1 42 96">
  <path
    d = "M 65.11969 0.5439408 A 110 50 35.0 0 1 84.86389 93.29673"
    stroke = "#ff0000"
    stroke-dasharray = "none"
    stroke-dashoffset = "0mm"
    stroke-width = "2mm"
    stroke-linecap = "round"
    stroke-linejoin = "round"
    vector-effect = "non-scaling-stroke"
    fill = "none"/>
</svg>

Implementation in Proteus Schema

<TrimmedCurve StartAngle = "350.61" EndAngle = "54.44">
  <Ellipse PrimaryAxis = "110" SecondaryAxis = "50">
    <Presentation
      LineType = "0"
      LineWeight = "2"
      R = "1"
      G = "0"
      B = "0"/>
    <Position>
      <Location
        X = "10"
        Y = "-20"
        Z = "0"/>
      <Axis
        X = "0"
        Y = "0"
        Z = "1"/>
      <Reference
        X = "0.819152044"
        Y = "-0.573576436"
        Z = "0"/>
    </Position>
  </Ellipse>
</TrimmedCurve>

Example

We consider the same EllipseArc as in the previous example, except that the Stroke is 2mm #ff0000 Dash.

<svg
  xmlns = "http://www.w3.org/2000/svg"
  width = "42mm"
  height = "96mm"
  viewBox = "64 -1 42 96">
  <path
    d = "M 65.11969 0.5439408 A 110 50 35.0 0 1 84.86389 93.29673"
    stroke = "#ff0000"
    stroke-dasharray = "10mm 14mm"
    stroke-dashoffset = "0mm"
    stroke-width = "2mm"
    stroke-linecap = "round"
    stroke-linejoin = "round"
    vector-effect = "non-scaling-stroke"
    fill = "none"/>
</svg>

Implementation in Proteus Schema

<TrimmedCurve StartAngle = "350.61" EndAngle = "54.441930674">
  <Ellipse PrimaryAxis = "110" SecondaryAxis = "50">
    <Presentation
      LineType = "2"
      LineWeight = "2"
      R = "1"
      G = "0"
      B = "0"/>
    <Position>
      <Location
        X = "10"
        Y = "-20"
        Z = "0"/>
      <Axis
        X = "0"
        Y = "0"
        Z = "1"/>
      <Reference
        X = "0.819152044"
        Y = "-0.573576436"
        Z = "0"/>
    </Position>
  </Ellipse>
</TrimmedCurve>

Center

Attribute (data)

The center position of the EllipseArc.

Multiplicity: 1

Type: Point

EndAngle

Attribute (data)

The end angle of the EllipseArc, measured clockwise and in degrees. The value must be in the inverval [0; 360).

Multiplicity: 1

Type: Double

HorizontalSemiAxis

Attribute (data)

The length of the horizontal semi-axis of the EllipseArc in mm.

Multiplicity: 1

Type: Double

Rotation

Attribute (data)

The rotation of the EllipseArc around its center, measured clockwise and in degrees. The value must be in the inverval [0; 360).

Multiplicity: 1

Type: Double

StartAngle

Attribute (data)

The start angle of the EllipseArc, measured clockwise and in degrees. The value must be in the inverval [0; 360).

Multiplicity: 1

Type: Double

Stroke

Attribute (data)

The stroke of the EllipseArc.

Multiplicity: 1

Type: Stroke

VerticalSemiAxis

Attribute (data)

The length of the vertical semi-axis of the EllipseArc in mm.

Multiplicity: 1

Type: Double