|
1 #include "../algorithms/geometry.h" |
|
2 #include "../glShared.h" |
|
3 #include "../model.h" |
|
4 #include "../algorithms/invert.h" |
|
5 #include "circularprimitive.h" |
|
6 #include "quadrilateral.h" |
|
7 #include "primitives.h" |
|
8 |
|
9 QString LDCircularPrimitive::buildFilename() const |
|
10 { |
|
11 int numerator = this->m_segments; |
|
12 int denominator = this->m_divisions; |
|
13 QString prefix; |
|
14 |
|
15 if (m_divisions != MediumResolution) |
|
16 prefix = QString::number(m_divisions) + '\\'; |
|
17 |
|
18 simplify(numerator, denominator); |
|
19 |
|
20 switch (m_type) |
|
21 { |
|
22 case PrimitiveModel::Cylinder: |
|
23 return format("%1%2-%3cyli.dat", prefix, numerator, denominator); |
|
24 |
|
25 case PrimitiveModel::Circle: |
|
26 return format("%1%2-%3edge.dat", prefix, numerator, denominator); |
|
27 |
|
28 default: |
|
29 Q_ASSERT(false); |
|
30 return ""; |
|
31 } |
|
32 } |
|
33 |
|
34 LDCircularPrimitive::LDCircularPrimitive( |
|
35 PrimitiveModel::Type type, |
|
36 int segments, |
|
37 int divisions, |
|
38 const Matrix& transformationMatrix, |
|
39 const Vertex& position |
|
40 ) : |
|
41 LDMatrixObject {transformationMatrix, position}, |
|
42 m_type {type}, |
|
43 m_segments {segments}, |
|
44 m_divisions {divisions} {} |
|
45 |
|
46 LDObjectType LDCircularPrimitive::type() const |
|
47 { |
|
48 return SubclassType; |
|
49 } |
|
50 |
|
51 QString LDCircularPrimitive::asText() const |
|
52 { |
|
53 return LDSubfileReference(buildFilename(), transformationMatrix(), position()).asText(); |
|
54 } |
|
55 |
|
56 void LDCircularPrimitive::getVertices(DocumentManager* /* context */, QSet<Vertex>& vertices) const |
|
57 { |
|
58 int endSegment = (m_segments == m_divisions) ? m_segments : m_segments + 1; |
|
59 |
|
60 for (int i = 0; i < endSegment; i += 1) |
|
61 { |
|
62 QPointF point2d = pointOnLDrawCircumference(i, m_divisions); |
|
63 |
|
64 for (double y_value : {0.0, 1.0}) |
|
65 { |
|
66 Vertex vertex {point2d.x(), y_value, point2d.y()}; |
|
67 vertex.transform(transformationMatrix(), position()); |
|
68 vertices.insert(vertex); |
|
69 } |
|
70 } |
|
71 } |
|
72 |
|
73 bool LDCircularPrimitive::isRasterizable() const { return true; } |
|
74 |
|
75 void LDCircularPrimitive::rasterize( |
|
76 DocumentManager* context, |
|
77 Winding /* parentWinding */, |
|
78 Model& model, |
|
79 bool /* deep */, |
|
80 bool /* render */ |
|
81 ) { |
|
82 Model cylinderBody {context}; |
|
83 buildPrimitiveBody(cylinderBody); |
|
84 |
|
85 for (LDObject* object : cylinderBody.objects()) |
|
86 { |
|
87 for (int i = 0; i < object->numVertices(); i += 1) |
|
88 { |
|
89 Vertex vertex = object->vertex(i); |
|
90 vertex.transform(transformationMatrix(), position()); |
|
91 object->setVertex(i, vertex); |
|
92 } |
|
93 } |
|
94 |
|
95 model.merge(cylinderBody); |
|
96 } |
|
97 |
|
98 QVector<LDPolygon> LDCircularPrimitive::rasterizePolygons(DocumentManager* context, Winding winding) |
|
99 { |
|
100 Model cylinderBody {context}; |
|
101 buildPrimitiveBody(cylinderBody); |
|
102 QVector<LDPolygon> result; |
|
103 bool cachedShouldInvert = shouldInvert(winding, context); |
|
104 |
|
105 for (LDObject* object : cylinderBody.objects()) |
|
106 { |
|
107 for (int i = 0; i < object->numVertices(); i += 1) |
|
108 { |
|
109 Vertex vertex = object->vertex(i); |
|
110 vertex.transform(transformationMatrix(), position()); |
|
111 object->setVertex(i, vertex); |
|
112 } |
|
113 |
|
114 LDPolygon* polygon = object->getPolygon(); |
|
115 |
|
116 if (polygon) |
|
117 { |
|
118 if (cachedShouldInvert) |
|
119 invertPolygon(*polygon); |
|
120 |
|
121 result.append(*polygon); |
|
122 } |
|
123 |
|
124 delete polygon; |
|
125 } |
|
126 |
|
127 return result; |
|
128 } |
|
129 |
|
130 void LDCircularPrimitive::buildPrimitiveBody(Model& model) const |
|
131 { |
|
132 PrimitiveModel primitive; |
|
133 primitive.type = m_type; |
|
134 primitive.segments = m_segments; |
|
135 primitive.divisions = m_divisions; |
|
136 primitive.ringNumber = 0; |
|
137 primitive.generateBody(model); |
|
138 } |
|
139 |
|
140 QString LDCircularPrimitive::objectListText() const |
|
141 { |
|
142 QString result = format( |
|
143 "%1 %2 %3, (", |
|
144 PrimitiveModel::typeName(m_type), |
|
145 m_segments / m_divisions, |
|
146 position().toString(true) |
|
147 ); |
|
148 |
|
149 for (int i = 0; i < 9; ++i) |
|
150 result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : ""); |
|
151 |
|
152 result += ')'; |
|
153 return result; |
|
154 } |
|
155 |
|
156 int LDCircularPrimitive::triangleCount(DocumentManager*) const |
|
157 { |
|
158 switch (m_type) |
|
159 { |
|
160 case PrimitiveModel::Ring: |
|
161 case PrimitiveModel::Cone: |
|
162 throw std::logic_error("Bad primitive type to LDCircularPrimitive"); |
|
163 |
|
164 case PrimitiveModel::Cylinder: |
|
165 return 2 * m_segments; |
|
166 |
|
167 case PrimitiveModel::Disc: |
|
168 case PrimitiveModel::DiscNegative: |
|
169 return m_segments; |
|
170 |
|
171 case PrimitiveModel::Circle: |
|
172 return 0; |
|
173 } |
|
174 |
|
175 return 0; |
|
176 } |
|
177 |
|
178 QString LDCircularPrimitive::typeName() const |
|
179 { |
|
180 return "circular-primitive"; |
|
181 } |
|
182 |
|
183 void LDCircularPrimitive::serialize(class Serializer& serializer) |
|
184 { |
|
185 LDMatrixObject::serialize(serializer); |
|
186 serializer << m_segments << m_divisions; |
|
187 } |