Skip to content

Commit cfb8367

Browse files
authored
Merge pull request #21 from andrsd/insc-poly
Adding `InscribedPolygon`
2 parents 531d327 + 20a3d41 commit cfb8367

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

include/formo/inscribed_polygon.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-FileCopyrightText: 2024 David Andrs <andrsd@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
#pragma once
5+
6+
#include "formo/wire.h"
7+
#include <vector>
8+
9+
namespace formo {
10+
11+
class Axis2;
12+
class Point;
13+
class Vector;
14+
15+
class InscribedPolygon : public Wire {
16+
public:
17+
/// Create circumscribed polygon from radius and number of sides
18+
///
19+
/// @param radius Radius if the circle
20+
/// @param sides Number of sides (must be 3 or more)
21+
InscribedPolygon(const Axis2 & ax2, double radius, int sides);
22+
23+
/// Create circumscribed polygon from a point and number of sides
24+
///
25+
/// @param pt1 Point defining the circle and the first point of the polygon
26+
/// @param sides Number of sides (must be 3 or more)
27+
InscribedPolygon(const Axis2 & ax2, const Point & pt1, int sides);
28+
29+
private:
30+
std::vector<Point> build_points(const Axis2 & ax2, const Vector & vec);
31+
TopoDS_Wire build_polygon(const std::vector<Point> & points);
32+
33+
/// Radius of the circle
34+
double radius;
35+
/// Number of sides
36+
int n_sides;
37+
};
38+
39+
} // namespace formo

python/src/formo.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "formo/geometry.h"
2424
#include "formo/iges_file.h"
2525
#include "formo/io.h"
26+
#include "formo/inscribed_polygon.h"
2627
#include "formo/line.h"
2728
#include "formo/linear_pattern.h"
2829
#include "formo/operations.h"
@@ -274,6 +275,13 @@ PYBIND11_MODULE(formo, m)
274275
py::arg("ax2"), py::arg("pt1"), py::arg("sides"))
275276
;
276277

278+
py::class_<InscribedPolygon, Wire>(m, "InscribedPolygon")
279+
.def(py::init<const Axis2 &, double, int>(),
280+
py::arg("ax2"), py::arg("radius"), py::arg("sides"))
281+
.def(py::init<const Axis2 &, const Point &, int>(),
282+
py::arg("ax2"), py::arg("pt1"), py::arg("sides"))
283+
;
284+
277285
//
278286

279287
py::class_<ArcOfCircle, Edge>(m, "ArcOfCircle")

src/inscribed_polygon.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-FileCopyrightText: 2024 David Andrs <andrsd@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
#include "formo/inscribed_polygon.h"
5+
#include "formo/axis1.h"
6+
#include "formo/axis2.h"
7+
#include "formo/point.h"
8+
#include "formo/vector.h"
9+
#include "formo/exception.h"
10+
#include "BRepBuilderAPI_MakePolygon.hxx"
11+
12+
namespace formo {
13+
14+
InscribedPolygon::InscribedPolygon(const Axis2 & ax2, double radius, int sides) :
15+
Wire(),
16+
radius(radius),
17+
n_sides(sides)
18+
{
19+
if (sides < 3)
20+
throw Exception("InscribedPolygon needs at least 3 sides");
21+
22+
auto r_out = radius / (0.5 * std::sqrt(3));
23+
auto points = build_points(ax2, r_out * ax2.x_direction());
24+
auto polygon = build_polygon(points);
25+
set_wire(polygon);
26+
}
27+
28+
InscribedPolygon::InscribedPolygon(const Axis2 & ax2, const Point & pt1, int sides) :
29+
Wire(),
30+
radius(0.),
31+
n_sides(sides)
32+
{
33+
if (sides < 3)
34+
throw Exception("InscribedPolygon needs at least 3 sides");
35+
36+
auto vec = Vector(ax2.location(), pt1);
37+
this->radius = vec.magnitude();
38+
auto r_out = this->radius / (0.5 * std::sqrt(3));
39+
auto points = build_points(ax2, r_out * vec);
40+
auto polygon = build_polygon(points);
41+
set_wire(polygon);
42+
}
43+
44+
std::vector<Point>
45+
InscribedPolygon::build_points(const Axis2 & ax2, const Vector & start_vec)
46+
{
47+
std::vector<Point> points;
48+
auto ctr_pt = ax2.location();
49+
Axis1 ctr_ax1(ctr_pt, ax2.direction());
50+
auto dangle = 2 * M_PI / n_sides;
51+
for (int i = 0; i < n_sides; i++) {
52+
auto vec = start_vec.rotated(ctr_ax1, i * dangle);
53+
auto pt1 = ctr_pt + vec;
54+
points.emplace_back(pt1);
55+
}
56+
return points;
57+
}
58+
59+
TopoDS_Wire
60+
InscribedPolygon::build_polygon(const std::vector<Point> & points)
61+
{
62+
BRepBuilderAPI_MakePolygon polygon;
63+
for (auto & pt : points)
64+
polygon.Add(pt);
65+
polygon.Close();
66+
polygon.Build();
67+
if (!polygon.IsDone())
68+
throw Exception("Polygon was not created");
69+
return polygon.Wire();
70+
}
71+
72+
} // namespace formo

test/src/InscribedPolygon_test.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "gmock/gmock.h"
2+
#include "formo/inscribed_polygon.h"
3+
#include "formo/axis2.h"
4+
#include "formo/direction.h"
5+
#include "formo/exception.h"
6+
7+
using namespace formo;
8+
9+
TEST(InscribedPolygonTest, ctor1)
10+
{
11+
Axis2 ax2(Point(1, 1, 0), Direction(0, 0, 1));
12+
InscribedPolygon plgn(ax2, 2, 3);
13+
14+
EXPECT_THROW({ InscribedPolygon(ax2, 2, 1); }, Exception);
15+
}
16+
17+
TEST(InscribedPolygonTest, ctor2)
18+
{
19+
Axis2 ax2(Point(1, 1, 0), Direction(0, 0, 1));
20+
InscribedPolygon plgn(ax2, Point(0, 1, 0), 3);
21+
22+
EXPECT_THROW({ InscribedPolygon(ax2, Point(0, 1, 0), 1); }, Exception);
23+
}

0 commit comments

Comments
 (0)