(Urgent) Rotation about a point of origin by no.of sides

Hi, So I have been given a number of sides, which is 4, then I have also been given an origin point, and a first point of a RPolygon. My frustration with this is that I am not able to get the rotation correct. My RPolygon inherits from Polygon class which has the rotate function. How do I make use of the rotate function in my polygon class such that I am able to rotate all the points of RPolygon by its number of sides to get the correct output? I have only been given a first point. Would appreciate your input. Note: I have to keep all of the classes and only main() should not be touched. Rotate() function parameter should leave as one param.

Thank you very much

Correct Output:

1 1

0 0

1 -1

2 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include <iostream>

#include <string>

#include <cmath>


template <typename T>

class Vector
{
public:
	using type = T;
	type x() const;
	type y() const;
	Vector();
	Vector(type x, type y);
private:
	type _x;
	type _y;
};

template <typename T>

Vector<T>::Vector() :
	_x{},_y{}
{}

template <typename T>

Vector<T>::Vector(type x, type y) :
	_x{ x },
	_y{ y }
{}

template <typename T>

typename Vector<T>::type Vector<T>::x() const
{
	return _x;
}

template <typename T>

typename Vector<T>::type Vector<T>::y() const
{
	return _y;
}

template<class T>

class Point
{

public:
	using type = typename T::type;


	Point() {}

	Point(T pts) : _pts(pts) {}

	int x() const
	{
		return _pts.x();
	}
	int y() const
	{
		return _pts.y();
	}

protected:
	T _pts;
};

class I_Rotatable
{

public:

	virtual void rotate(float factor) = 0;

};

template<typename T>

class Polygon : public Point<T>, public I_Rotatable
{

public:

	Polygon() {}

	Polygon(const unsigned int size, T* points) : Point<T>(T(0, 0)), _size(size)
	{
		n_ptr = new T[_size];

		for (int i{}; i < _size; i++)
		{

			n_ptr[i] = points[i];
		}
		Point<T>::_pts = T((points[0].x() + points[1].x() + points[2].x()) / size,

			(points[0].y() + points[1].y() + points[2].y()) / size);
	}

	int size() const
	{
		return _size;
	}
	const T* points()
	{
		return n_ptr;
	}

	void rotate(float factor) override
	{
		float _mx, _my;

		for (int i{}; i < _size; i++)
		{
			float _nx = n_ptr[i].x() - Point<T>::_pts.x();

			float _ny = n_ptr[i].y() - Point<T>::_pts.y();

			_mx = Point<T>::_pts.x() + std::cos(factor) * _nx - std::sin(factor) * _ny;

			_my = Point<T>::_pts.y() + std::sin(factor) * _nx + std::cos(factor) * _ny;

			n_ptr[i] = T(_mx, _my);
		}
	}

	~Polygon()
	{
		delete[] n_ptr;
	}

protected:

	unsigned int _size;

	T* n_ptr;

};

template<typename T>

class RPolygon : public Polygon<T>
{
public:
	RPolygon(T origin, T firstpt, const int sides, T* pts = new T(0, 0))

		: Polygon<T>(sides, pts)
	{

		//Need help here.
		Point<T>::_pts = T(origin.x(), origin.y());
	}

private:

};

int main()
{
	float PI = 2 * acos(0.0);

	using vector = Vector<int>;

	RPolygon<vector> RPolygon{

			 {1, 0},

			 {2, 0},

			 4
	};

	I_Rotatable& rotatable = RPolygon;

	rotatable.rotate(PI / 2.0f);

	const vector* pts = RPolygon.points();

	if ((RPolygon.size() != 4) ||

		(pts[0].x() != 1) || (pts[0].y() != 1) ||

		(pts[1].x() != 0) || (pts[1].y() != 0) ||

		(pts[2].x() != 1) || (pts[2].y() != -1) ||

		(pts[3].x() != 2) || (pts[3].y() != 0))

	{

		std::cout << pts[0].x() << " " << pts[0].y() << std::endl;

		std::cout << pts[1].x() << " " << pts[1].y() << std::endl;

		std::cout << pts[2].x() << " " << pts[2].y() << std::endl;

		std::cout << pts[3].x() << " " << pts[3].y() << std::endl;

		std::cout << "I_Rotatable has failed.";

	}

}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <math.h>

struct vector2 { double x = 0, y = 0; };

vector2 operator+(vector2 v, vector2 u) { return {(v.x + u.x), (v.y + u.y)}; }
vector2 operator-(vector2 v, vector2 u) { return {(v.x - u.x), (v.y - u.y)}; }
vector2 rotate(vector2 v, double theta)
{
  return { v.x*cos(theta) - v.y*sin(theta), v.x*sin(theta) + v.y*cos(theta) };
}

std::vector<vector2>
regular_polygon(vector2 origin, vector2 vertex, int sides)
{
  std::vector<vector2> result;
  for (int i = 0; i < sides; ++i)
    result.push_back(origin + rotate(vertex - origin, (i*2*(4*atan(1)) / sides)));
  return result;
}

int main()
{
  for (auto [x, y]: regular_polygon({1, 0}, {2, 0}, 4))
    std::cout << "<" << lround(x) << ", " << lround(y) << ">\n"; 
}

Live demo:
http://coliru.stacked-crooked.com/a/6a0327df3d2137ee

It's a simple problem. But the original post seems to have lost sight of that problem within a morass of abstraction. Surely, the type hierarchies and class templates aren't making the problem any easier. Why do they exist?

This is an assignment, right? Which parts of your current program are you required to keep as part of your solution? (Ideally, you would rip everything out.)
Last edited on
Hi, Sorry I do not understand. Do you mind helping me with my code above so I am able to understand more clearly and easily? Thanks. I also do not know how to apply what u have given me into my code. I'm not well versed with programming. But trying my best.
Yup. Its an assignment. I have to keep all of the classes and only main() should not be touched. Sorry for not mentioning earlier. Just add on, Ideally, no removal of anything plz. Rotate() function parameter cannot change. it only accepts angle as one param.
Last edited on
> My frustration with this is that I am not able to get the rotation correct.
your rotation is fine, the problem is with your polygon construction
¿where do you even set the coordinates of the vertices?

also, your class relationships are weird
you derive `Polygon' from `Point' only to have a `_pts' (terrible name) member variable, which have a different meaning every time
Point::_pts is the position
Polygon::_pts is the center of mass
RPolygon::_pts is the origin of the rotation
Last edited on
Yes, sorry about that.
Hi, So this is the updated code I did in my RPolygon Ctor, trying to implement mbozzi's code into mine. However, I'm still not able to get the desired output. Is anyone able to help? Really at a loss here. Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <iostream>

#include <string>

#include <cmath>
#include <vector>


template <typename T>

class Vector

{

public:

	using type = T;
	type x() const;
	type y() const;
	Vector();
	Vector(type x, type y);
private:
	type _x;
	type _y;

};

template <typename T>

Vector<T>::Vector() :
	_x{},_y{}
{}

template <typename T>

Vector<T>::Vector(type x, type y) :
	_x{ x },
	_y{ y }
{}

template <typename T>

typename Vector<T>::type Vector<T>::x() const
{
	return _x;
}


template <typename T>

typename Vector<T>::type Vector<T>::y() const
{
	return _y;
}

template<class T>

class Point
{

public:
	using type = typename T::type;


	Point() {}

	Point(T pts) : _pts(pts) {}

	int x() const
	{
		return _pts.x();
	}
	int y() const
	{
		return _pts.y();
	}

protected:
	T _pts;
};

class I_Rotatable
{

public:

	virtual void rotate(float factor) = 0;

};

template<typename T>

class Polygon : public Point<T>, public I_Rotatable
{

public:

	Polygon() {}

	Polygon(const unsigned int size, T* points) : Point<T>(T(0, 0)), _size(size)
	{
		n_ptr = new T[_size];

		for (int i{}; i < _size; i++)
		{

			n_ptr[i] = points[i];
		}
		Point<T>::_pts = T((points[0].x() + points[1].x() + points[2].x()) / size,

			(points[0].y() + points[1].y() + points[2].y()) / size);
	}

	int size() const
	{
		return _size;
	}
	const T* points()
	{
		return n_ptr;
	}

	void rotate(float factor) override
	{
		float _mx, _my;

		for (int i{}; i < _size; i++)
		{
			float _nx = n_ptr[i].x() - Point<T>::_pts.x();

			float _ny = n_ptr[i].y() - Point<T>::_pts.y();

			_mx = Point<T>::_pts.x() + std::cos(factor) * _nx - std::sin(factor) * _ny;

			_my = Point<T>::_pts.y() + std::sin(factor) * _nx + std::cos(factor) * _ny;

			n_ptr[i] = T(_mx, _my);
		}
	}

	~Polygon()
	{
		delete[] n_ptr;
	}

protected:

	unsigned int _size;
	T* n_ptr;

};
 
template<typename T>

class RPolygon : public Polygon<T>
{
public:
	RPolygon(T origin, T vertex, const int sides, T* pts = new T(0, 0))

		: Polygon<T>(sides, pts)
	{
		std::vector<T> result;
		Polygon<T>::n_ptr[0] = origin;
		Point<T>::_pts = T(origin.x(), origin.y());
		for (int i = 0; i < sides; ++i)
		{
			float _xn, _yn;
float n_x = static_cast<float>(Polygon<T>::n_ptr[i].x() - Point<T>::_pts.x()); //origin - vertex
			float n_y = static_cast<float>(Polygon<T>::n_ptr[i].y() - Point<T>::_pts.y());
			//¿what do you think you are doing here?
			result.push_back(T{ static_cast<int>(std::round(static_cast<float>(Point<T>::_pts.x()) +
							std::cos(angle) * n_x - std::sin(angle) * n_y)), 
					static_cast<int>(std::round(static_cast<float>(Point<T>::_pts.y()) +
								std::sin(angle) * n_x + std::cos(angle) * n_y)) });
			
 		}
 
		for (int i{}; i < sides; i++)
		{
			Polygon<T>::n_ptr[i] = result[i];
		}
 	}

private:

};

int main()
{
	float PI = 2 * acos(0.0);

	using vector = Vector<int>;

	RPolygon<vector> RPolygon{

			 {1, 0},

			 {2, 0},

			 4
	};

	I_Rotatable& rotatable = RPolygon;

	rotatable.rotate(PI / 2.0f);

	const vector* pts = RPolygon.points();

	if ((RPolygon.size() != 4) ||

		(pts[0].x() != 1) || (pts[0].y() != 1) ||

		(pts[1].x() != 0) || (pts[1].y() != 0) ||

		(pts[2].x() != 1) || (pts[2].y() != -1) ||

		(pts[3].x() != 2) || (pts[3].y() != 0))

	{

		std::cout << pts[0].x() << " " << pts[0].y() << std::endl;

		std::cout << pts[1].x() << " " << pts[1].y() << std::endl;

		std::cout << pts[2].x() << " " << pts[2].y() << std::endl;

		std::cout << pts[3].x() << " " << pts[3].y() << std::endl;

		std::cout << "I_Rotatable has failed.";

	}


}
Last edited on
I'll repeat: ¿where do you even set the coordinates of the vertices?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
RPolygon(T origin, T vertex, const int sides, T* pts = new T(0, 0))
	: Polygon<T>(sides, pts)
{
	//at this point n_ptr already has size 4
	//¿what values does it hold?
	std::vector<T> result; //if you know std::vector ¿why don't you use it for the vertex array?
	Polygon<T>::n_ptr[0] = origin;
	Point<T>::_pts = T(origin.x(), origin.y());
	//there you set n_ptr[0] and center_of_mass to origin
	//¿what about n_ptr[1], n_ptr[2] and n_ptr[3]?
	for (int i = 0; i < sides; ++i)
	{
		float _xn, _yn;
		const float angle = (2.0f * std::acos(-float{ 1 })) / static_cast<float>(sides);
		for (unsigned int i{}; i < sides; i++) //¿nested?
		{
			float n_x = static_cast<float>(Polygon<T>::n_ptr[i].x() - Point<T>::_pts.x()); //origin - vertex
			float n_y = static_cast<float>(Polygon<T>::n_ptr[i].y() - Point<T>::_pts.y());
			//¿what do you think you are doing here?
			result.push_back(T{ static_cast<int>(std::round(static_cast<float>(Point<T>::_pts.x()) +
							std::cos(angle) * n_x - std::sin(angle) * n_y)), 
					static_cast<int>(std::round(static_cast<float>(Point<T>::_pts.y()) +
								std::sin(angle) * n_x + std::cos(angle) * n_y)) });
		}

	}
	//bother yourself and check the content of `result'

	for (int i{}; i < sides; i++)
	{
		Polygon<T>::n_ptr[i] = result[i];
	}
}


1
2
3
RPolygon(T origin, T vertex, const int sides, T* pts = new T(0, 0))
	: Polygon<T>(sides, pts)
{}
that alone would be incorrect because of your crappy memory management, `pts' is not an array, it just hold one value, and it's causing a memory leak
given that at this point you do not have the coordinates of all your vertices, you better just use the default constructor of Polygon
Polygon(): _size(0), n_ptr(nullptr){}
Last edited on
Topic archived. No new replies allowed.