====================
Circles and ellipses
====================

A circle is defined by three points on the edge of the circle using ``Insert_Circle`` (using non colinear points), or via a center point and radius using ``Insert_Circle_By_Radius``. An ellipse is defined by a center point, and major and minor axis points. 

In addition to commands to insert circles, HOOPS also has commands to insert circular arcs ( ``Insert_Circular_Arc`` ), elliptical arcs ( ``Insert_Elliptical_Arc`` ), circular chords ( ``Insert_Circular_Chord`` ) and circular wedges ( ``Insert_Circular_Wedge`` ). 


Circle and ellipse attributes
=============================

Like a polygon, circles and ellipses have an edge and a face. All attributes that apply to polygons also apply to circles and ellipses (including edge pattern, but not including the "line join" part of the edge pattern, since the edges of circles/ellipses do not contain separate segments with line joins). 


Wire circles
------------

If you wish to represent a wire circle, one valid approach is to use the 'circle' primitive and turn off the visibility of 'faces' for the segment that the circle resides in. But that would turn off all faces in the segment,which might not be desirable. The next logical thing would be to put such circle primitives in a subsegment and make the appropriate visibility setting in there ("faces = off, edges = on"). However, there's a better solution. Instead of creating a subsegment, you can use an elliptical arc (with start=0.0 and end=1.0) to represent a 'wire' circle, and therefore would not have to turn faces off or place the geometry in a subsegment. The following code snippet is an example of how to create a unit wire circle centered at the origin in the xy plane using ``Insert_Elliptical_Arc``:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0012.cpp
		   :start-after: //! [insert_elliptical_arc]
		   :end-before: //! [insert_elliptical_arc]
		   

Precision control
=================

There is a trade off between performance and rendering quality for all 'curve' primitives. To manage this balance, one can utilize  the 'general curve' settings in ``Set_Rendering_Options`` to allow the user to try to maintain an appropriate number of vertices for the 'curve' component of each primitive. The settings available primarily depend on whether or not the curves are view-dependent or view independent.


View-independent curves
-----------------------

View-independent curves are pre-tessellated into a group of static line segments which are stored and redrawn on each update, and are the fastest way to render curves. They are enabled by setting the 'general curve = (view independent)' option of ``Set_Rendering_Options``: 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0012.cpp
		   :start-after: //! [view_independent]
		   :end-before: //! [view_independent]
		   
The drawback is that there are no run-time checks to make sure that no visual artifacts are popping in, which could occur with extreme zoom-in levels. Refer to the 'general curve' docs for details on other suboptions which control how HOOPS/3dGS tessellated view-independent curves


View-dependent curves
---------------------

View-dependent curves are re-tessellated on every update. It is an expensive process, it is the only way to be completely certain that no artifacts will appear. They are enabled by setting the "general curve = (view dependent)" option of ``Set_Rendering_Options``: 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0012.cpp
		   :start-after: //! [view_dependent]
		   :end-before: //! [view_dependent]
		   
The tolerance is dependent on what driver is currently active, but there is currently no interface to specify tolerance (read: it's hard coded until someone asks us to do otherwise).  Curves put through OpenGL are tessellated until each line segment is no longer than 5 pixels long. All other drivers use upper-level HOOPS to calculate the tessellation, which recursively subdivides until adjacent control points are within 2 pixels of one another.


Clock example using circles
===========================

In the next version of the clock, we use two circles: one to replace the face of the clock, and one to replace the central hub. We use the ``Insert_2D_Circle`` routine defined above. 

The segment containing the hands is the same, so we shall look at only the rest of the clock, which draws the clock face and the hour numerals:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0012.cpp
		   :start-after: //! [clock_example]
		   :end-before: //! [clock_example]
		   