# How to obtain an arbitrary point on a circle using HPS

**URL:** <https://forum.techsoft3d.com/t/how-to-obtain-an-arbitrary-point-on-a-circle-using-hps/4291>\
**Category:** HOOPS Visualize Desktop\
**Tags:** code, knowledge-base, how-to, circle\
**Created:** [December 19, 2024, 10:05pm UTC](https://forum.techsoft3d.com/t/how-to-obtain-an-arbitrary-point-on-a-circle-using-hps/4291 "2024-12-19T22:05:34Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![mike](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.techsoft3d.com/mike/32/228_2.png) [@mike](https://forum.techsoft3d.com/u/mike)\
**Post date:** [December 19, 2024, 10:05pm UTC](https://forum.techsoft3d.com/t/how-to-obtain-an-arbitrary-point-on-a-circle-using-hps/4291/1 "2024-12-19T22:05:34Z")

</div>

Using Visualize 3DF, a circle could be created using a center point, normal vector and radius. Subsequently, the 3DF API supported obtaining three points on the circle (even when the three point method of defining a circle was not used).

In HPS, `InsertCircle()` returns a `CircleKey`. The [CircleKey](https://docs.techsoft3d.com/hps/latest/api_ref/cpp/class_h_p_s_1_1_circle_key.html) has a `ShowRadius()` method. Alternatively, you can use the `CircleKey` to `Show()` or copy the contents (definition) of the `CircleKey` into a `CircleKit` which has a `ShowRadius()` method. In this case, the radius is integral to the definition of the circle. This is analogous to the 3DF functions `Insert_Circle_By_Radius` and `Show_Circle_By_Radius`.

Similarly, `InsertCircularArc()` returns a `CircularArcKey`. The [CircularArcKey](https://docs.techsoft3d.com/hps/latest/api_ref/cpp/class_h_p_s_1_1_circular_arc_key.html) has methods to _Show_ the three points used to define the arc. Alternatively you can use the `CircleArcKey` to `Show()` or copy the contents (definition) of the `CircularArcKey` into a `CircularArcKit` which has similar _Show_ methods. In this case, the radius is not part of the arc’s defining parameters. This is analogous to the 3DF functions `Insert_Circular_Arc` and `Show_Circular_Arc`.

Unlike 3DF, there is no HPS API _crossover_ where three points can be obtained for a circle defined by a center and radius. Given the center, normal and radius, you could compute one or more points on the circle.

The following code can be used in the MFC Sandbox;

```auto
class RandomCircle {
public:
	RandomCircle(HPS::Point &c, HPS::Vector& n, float r)
	{
		srand(time(NULL));
		center = c;
		normal = n;
		radius = r;
	}

	HPS::Point PointAt(float angle)
	{
		float xv = (float)cos(angle);
		float yv = (float)sin(angle);

		HPS::Vector v = findV();
		HPS::Vector w = v.Cross(normal);

		// Return center + r * (V * cos(a) + W * sin(a))
		HPS::Vector r1 = v * (radius * xv);
		HPS::Vector r2 = w * (radius * yv);

		return HPS::Point(center.x + r1.x + r2.x,
			center.y + r1.y + r2.y,
			center.z + r1.z + r2.z);
	}
	void Randomize()
	{
		// randomize the circle parameters
		center.x = GetRandomFloat();
		center.y = GetRandomFloat();
		center.z = GetRandomFloat();

		normal.x = GetRandomFloat();
		normal.y = GetRandomFloat();
		normal.z = GetRandomFloat();
		normal.Normalize();

		radius = GetRandomFloat() / radiusFraction;
	}

	HPS::Point center;
	float radius;
	HPS::Vector normal;

private:
	RandomCircle() {}

	HPS::Vector findV()
	{
		HPS::Vector vp = {0, 0, 0};
		if (normal.x != 0 || normal.y != 0) {
			vp = {0, 0, 1};
		}
		else if (normal.x != 0 || normal.z != 0) {
			vp = {0, 1, 0};
		}
		else if (normal.y != 0 || normal.z != 0) {
			vp = {1, 0, 0};
		}
		else {
			return vp; // This is not good...
		}
		HPS::Vector cp = normal.Cross(vp);
		return cp.Normalize();
	}

	float GetRandomFloat()
	{
		float x = magnitude + 1;
		while (x > magnitude)
			x = 1 + rand() / ((RAND_MAX + 1u) / magnitude);

		return x - (magnitude / 2);
	}

	const float magnitude = 250;
	const float radiusFraction = 10;
};

void CHPSView::OnUserCode2()
{
	HPS::View aView = GetCanvas().GetFrontView();
	HPS::SegmentKey modelKey = aView.GetAttachedModel().GetSegmentKey();
	HPS::SegmentKey parentKey = modelKey.Down("circles", true);
	parentKey.GetVisibilityControl().SetGeometry(true);

	// Start with a unit circle in the XY plane
	RandomCircle rc(HPS::Point(0, 0, 0), HPS::Vector(0, 0, 1), 1.0f);

	HPS::SegmentKey unitCircleKey = parentKey.Down("unit circle", true);
	unitCircleKey.InsertCircle(rc.center, rc.radius, rc.normal);
	unitCircleKey.InsertMarker(rc.PointAt(0));
	unitCircleKey.InsertLine(rc.center, (rc.center + rc.normal));
	unitCircleKey.GetMaterialMappingControl().
		SetLineColor(RGBAColor(0, 1, 0)).
		SetMarkerColor(RGBAColor(0, 0, 1)).
		SetFaceColor(RGBAColor(1, 0, 0));

	// Add additional arbitrary circles
	int count = 100;
	for (int i = 0; i < count; i++)
	{
		rc.Randomize();
		parentKey.InsertCircle(rc.center, rc.radius, rc.normal);
		parentKey.InsertMarker(rc.PointAt(0));
		parentKey.InsertLine(rc.center, (rc.center + rc.normal));
	}
	aView.FitWorld();
	aView.Update();
}

```

It generates a scene with a unit circle at the origin and 100 other random circles with a point on the circle and the normal. The point is calculated for a given angle around the circle (alpha = 0 in this case).

 ![image](https://us1.discourse-cdn.com/flex020/uploads/techsoft3d/original/2X/7/72a3a28294e29c26a96a50df9f04c5c4fbadeaf0.png)
