I would like the image to always have a 'point' at the top rather than centre right - ie. how can I rotate it 90º anti clockwise.
Thid is set up in the "Define()" method of the TReleauxPolygon where the polygon corner points are calculated. My original routine initialized the angle parameter with phi = 0 - this is the angle with respect to the x axis. In order for the first point to be on the y axis initialize with 90 degrees. But note that the routine already works with radians, so 90° = pi/2. And note also that the y axis of the Canvas points downwards - to have the first point at the top you must select phi = -pi/2. This is like winni's "startAngle". I'd recommend to make this a variable of the class (add to private "FStartAngle: Double), it has the advantage that you an add a timer and in each OnTimer event you can simple increment FStartAngle by a few degress and call Invalidate of the Paintbox - this way the polygon will rotate.
but since that code is only .lpi I can't easily compile and run.
Open a new project, but now do not select "Application", but "Simple Program" in the "Project" node of the "New..." dialog. Then click "select" above winni's code and copy the code to the clipboard (CTRL+C). Finally go back to lazarus into the empty project code windows, select everything and press CTRL+V to paste the clipboard over the template code. And you are ready to go.
I'm sure it will be some setting within procedure TReuleauxPolygon.Draw(ACanvas: TCanvas); but I can't see where.
It would be nice to have an 'outline' with a different colour from the fill. To this end I did try to change the Display.canvas.Pen.Color to clBlack but of course that simply draws a line around each of the circular Sectors so compromises the 'fill'. I suspect that needs extra code to overwrite the two straight lines of the sector after it has been drawn and filled.
Well, you can add color parameters to the TReuleaux.Draw() routine, and maybe also a linewidth parameter:
procedure TReuleaux.Draw(ACanvas: TCanvas; AFillColor, ABorderColor: TColor; ABorderLinewidth: Integer);
Set these parameters before the i loop.
To draw the border do not use the ACanvas.Pen because the routine calls ACanvas.Pie which draws something like a "pie of a birthday cake", and as you noted there are all the radial strikes. Use the "Arc()" method instead - it has the same parameters as the Pie() method - and add it after the Pie() call. But since now Pie and Arc are called in an alternating way you must make sure that the Pen is visible only in the Arc() routine, but not in the Pie(), otherwise there would be some radial strokes again. So, you must switch ACanvas.Pen.Style to psClear before the Pie() call and to psSolid before the Arc() call.
In some cases you will also see the rouding error such that the outline is not closed perfectly. One possibility is to avoid adding dPhi to the current value of phi because this will accumulate numerical errors. It is more accurate in the end to calculate the angle as "dphi*i + FStartAngle".
Because I want the Area calculation to be done after any modification you'll see that I have a discrete procedure for it which can be called when exiting either Nº of Sides or Diameter. That means that I have to be specific when addressing the variables - prefixing them with 'form1' - I believe that this is bad practice but don't know how to get around it.
Yes it is bad practice, mainly because you use global variables to store the result. Suppose you have two polygons in your programs. To which one will the global result variables refer? Another reason is that your calculation only works when the form variable is named "Form1", but you can create any instance of TForm1 with any name... You could make "Area", "Dia" and "N_S" variables of the form. But still: when there are two polygons on the same form...?
In my code I had set up the Reuleaux polygon as a separate class to have everything in place. And this is where the calculation should go. Either add public functions CalcDiameter and CalcArea, or introduce readonly properties Diameter and Area with these as getter methods (it would be common practice to name them GetDiameter and GetArea here).
I noticed here that you obviously misunderstood the "Radius" parameter of my routine as the "Diameter" of the ReuleauxPolygon - this is not correct. In my code the "Radius" is the radius of the circle with the generating corner points. Your "Diameter" is the distance from one corner point to the center of the opposite circle. This is excactly the radius of the circle segments drawn. There is a routine in TReuleauxPolygon for it, CircleRadius(). I think using the polygon diameter instead of the point radius in the Create() and Define() routines is more practical - but I leave it as an excercise to you to modify the code accordingly.
In the attachment I modified your code as described above. Study it and ask if you do not understand something. It has all the Reuleaux-related code in a separate code which thus can be reused in any application.
I'm curious as to why the uses clause for 'Math' is in the implementation section rather than the Interface section. I would normally add it in the Interface.
Having units in the interface part of large projects will sooner or later lead to circular references where unit "A" uses unit "B" and unit B" uses unit "A". Pascal does not resolve these and stops compilation. Only when units are in the implementation section the situation can be resolved. Believe me, it is a pain resolving this error situation in large projects. Therefore I always follow the strategy to put units into the implementation section first, and only when the compiler tells me that he cannot find something in the interface section I move the unit up to interface.