Object2D - simple shapes

It seems Object2D has FigureShape which allows you to append Lines and Bezier Curves, and ArchShape which will produce Oval/Circular “curves”

But there is no way to append the two?
I need to create a fairly simple shape. one that is 1/2 circle on one end, and squared on the other
I then need to render that “shape” as both an unborderd solid color, and a non-filled, bordered shape

all within the confines of a bounding rectangle
the reason for both “modes” is I need the solid color to create a mask, and the non-filled to make a visible border

I am assuming that AddCubic cannot approximate 180deg of a circle very well, otherwise that could be used in FigureShape

What you need is the kind of shape used to create font glyphs.
SVG would handle this very well, but …

A figure shape expects the shape it describes to be a closed shape.

A solid shape of this kind is easy: A solid rectangle with a solid circle drawn at one end, with the centre at the edge of the rectangle.
But that doesn’t get the hollow version.

For hollow - consider the rectangle part:
corners at
A - B
C - D

You can draw a curved line from A to C
If you then draw a 6 point figureshape from A to b, B to D, D to C, C to D, D to B, B to A
Then you should have a closed figure shape which is just the 3 lines of the rectangle. (untested)

I am still working out the math, but it turns out you CAN approximate a Circle (within 2%) using 4 Cubic Splines
And for the shapes that I’m needing 2% is less than 1px distortion…

FigureShape will in fact do what I want… it is just a matter of working out the math.
Here is the code for one of the shapes I wanted… Its rough and needs optimizing, but it provides the exact required shape

Dim fig As New FigureShape
Dim x As Single
Dim y As Single
Dim x2 As Single
Dim y2 As Single
Dim cx As Single
Dim cy As Single
Dim cx2 As Single
Dim cy2 As Single
Const c As Single=0.551915024494

g.ForeColor=Color.green
g.fillrect 0,0,g.width,g.height


Dim h As Integer=g.height-1
Dim w As Integer=g.width-1

h=h/2
x=g.width-h
y=g.height
'
fig.addline 0,y,x,y
'
x2=g.width
y2=h
'
cx=(c*h)+x
cy=g.height
'
cx2=h+x
cy2=(c*h)+h

fig.AddCubic(x,y,x2,y2,cx,cy,cx2,cy2)

//
x=g.width
y=h
'
x2=g.width-h
y2=0
'
'
cx=x
cy=h-(c*h)
'
cx2=(c*h)+x2
cy2=0
'
fig.AddCubic(x,y,x2,y2,cx,cy,cx2,cy2)
fig.addline x2,y2,0,0



fig.Border = 100
fig.BorderWidth=3
fig.BorderColor = Color.blue
fig.FillColor = Color.orange
'
g.DrawObject(fig, 0,0)

You need just one Cubic:

Instead of AddCubic, sometimes is better to create a CurveShape and then append to the figure.

'Not real code

Dim fig As New FigureShape
Dim c As New CurveShape

c.CREATE_CURVE_B_C

fig.addline A, B
fig.Append(c)
fig.addline C,D
fig.addline D,A

Actually no you can’t… it may LOOK like its a 180 deg arc… but it is not. a single cubic can accurately approximate up to 90 deg.
But thank you for you input

Hi Dave,
I don’t get exactly what you try to achieve, but as i understand it this could be a solution:
In the paint-event of a canvas:

g.ForeColor = Color.Green g.FillRect(0, 0, Me.Width, Me.Height) Dim r As New RoundRectShape r.Width = Me.Width - 6 + Me.height r.Height = Me.Height - 3 r.x = Me.width / 2 + 3 / 2 - Me.height / 2 r.y = Me.Height / 2 r.Border = 100 r.BorderColor = Color.blue r.FillColor = Color.Orange r.CornerHeight = r.y * 2 r.CornerWidth = r.y * 2 r.BorderWidth = 3 g.DrawObject(r) g.ForeColor = Color.Blue g.PenWidth = 3 g.DrawLine(0, 0, 0, Me.Top + Me.height)

Solved…

Private Sub drawShape(width as integer, height as integer, style as integer)
  Const c As Single=0.551915024494
  Dim fig As New FigureShape
  Dim h As Single = height
  Dim w As Single = width
  Dim r As Single = h/2
  Dim r2 As Single=(c*r)
  //
  zBackImage=New Picture(Width,height)
  Dim g      As Graphics   = zBackImage.Graphics
  Dim mask   As picture    = New Picture(Width,height)
  Dim mask_g As graphics   = mask.Graphics
  Select Case style
  Case 0,1 // rectangle
    fig.AddLine 0,0,w,0
    fig.AddLine w,0,w,h
    fig.AddLine w,h,0,h
    fig.AddLine 0,h,0,0
  Case 2 // rounded
    r=Min(20,h/4)
    r2=c*r
    fig.AddLine w-r,0,r,0
    fig.AddCubic(r,0,0,r,r-r2,0,0,r-r2)
    fig.AddLine 0,r,0,h-r
    fig.AddCubic(0,h-r,  r,h,  0,(h-r)+r2,r-r2,h)
    fig.AddLine r,h,w-r,h
    fig.AddCubic(w-r,h,  w,h-r,  (w-r)+r2,h,w,h-r+r2)
    fig.addline w,h-r,w,r
    fig.AddCubic(w,r,w-r,0,w,r-r2,(w-r)+r2,0)
  Case 3 // big rounded
    fig.AddLine w-r,0,r,0
    fig.AddCubic(r,0,0,r,r-r2,0,0,r-r2)
    fig.AddCubic(0,r,r,h,0,r+r2,r-r2,h)
    fig.AddLine r,h,w-r,h
    fig.AddCubic(w-r,h,w,r,(w-r)+r2,h,w,r+r2)
    fig.AddCubic(w,r,w-r,0,w,r-r2,(w-r)+r2,0)
  Case 4 //big round left
    fig.AddLine w,0,r,0
    fig.AddCubic(r,0,0,r,r-r2,0,0,r-r2)
    fig.AddCubic(0,r,r,h,0,r+r2,r-r2,h)
    fig.AddLine r,h,w,h
  Case 5 //big round right
    fig.AddLine 0,h,w-r,h
    fig.AddCubic(w-r,h,w,r,(w-r)+r2,h,w,r+r2)
    fig.AddCubic(w,r,w-r,0,w,r-r2,(w-r)+r2,0)
    fig.AddLine w-r,0,0,0
  Case 6
    r=Ceil(h/3)
    fig.addline 0,h,0,r
    fig.addline 0,r,r,0
    fig.addline r,0,w,0
    fig.addline w,0,w,h
  Case 7
    r=Ceil(h/3)
    fig.addline 0,h,0,r
    fig.addline 0,r,r,0
    fig.addline r,0,w,0
    fig.addline w,0,w,h
  End Select
  
  //
  // step 01 - create mask layer
  //
  mask_g.forecolor=Color.white
  mask_g.fillrect 0,0,mask_g.width,mask_g.height
  fig.Border = 0
  fig.FillColor = Color.black
  mask_g.DrawObject(fig,0,0) 
  
  g.ForeColor=Color.orange
  g.fillrect 0,0,g.Width,g.height
  
  //
  // Step 03 - Add Border
  //
  If style>0 Then 
    fig.border      = 100
    fig.BorderWidth = 3
    fig.BorderColor = Color.red
    fig.fill        = 0
    g.DrawObject(fig,0,0)
  End If
  //
  zBackImage.ApplyMask mask
  
End Sub

Draws 7 different closed shapes using FigureShape

[quote=422589:@Dave S]Actually no you can’t… it may LOOK like its a 180 deg arc… but it is not. a single cubic can accurately approximate up to 90 deg.
But thank you for you input[/quote]

That is right, the mathematical definition of a Bezier curve means it cannot reproduce any circular arc. A single cubic can approximate to 1/3rd of the arc. so, to aproximate 1/2, you need 2.

So, It all depends on the use. If you need the exact semicircle, yes use the two, if it is for some kind of UI, consider using the single one, as it results in a smother transition beetween the lines and the curve and a better looking shape.