fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4.  
  5. typedef struct Vector
  6. {
  7. double x;
  8. double y;
  9. double z;
  10. } Vector;
  11.  
  12. typedef struct Mesh
  13. {
  14. int a;
  15. int b;
  16. int c;
  17. } Mesh;
  18.  
  19. typedef struct Figure
  20. {
  21. int numPoints;
  22. Vector *points;
  23. int numMeshes;
  24. Mesh *meshes;
  25. int **boundary;
  26. } Figure;
  27.  
  28. Vector subtract(Vector v1, Vector v2)
  29. {
  30. Vector v = {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z};
  31. return v;
  32. }
  33.  
  34. double dot(Vector v1, Vector v2)
  35. {
  36. double result = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  37. return result;
  38. }
  39.  
  40. Vector cross(Vector v1, Vector v2)
  41. {
  42. Vector v;
  43. v.x = v1.y * v2.z - v1.z * v2.y;
  44. v.y = v1.z * v2.x - v1.x * v2.z;
  45. v.z = v1.x * v2.y - v1.y * v2.x;
  46. return v;
  47. }
  48.  
  49. void setBoundary(Figure *figure)
  50. {
  51. figure->boundary = malloc(sizeof(int *) * figure->numPoints);
  52. for (int i = 0; i < figure->numPoints; i++)
  53. {
  54. figure->boundary[i] = calloc(figure->numPoints, sizeof(int));
  55. }
  56. for (int i = 0; i < figure->numMeshes; i++)
  57. {
  58. int a = figure->meshes[i].a;
  59. int b = figure->meshes[i].b;
  60. int c = figure->meshes[i].c;
  61. figure->boundary[a][b]++;
  62. figure->boundary[b][c]++;
  63. figure->boundary[c][a]++;
  64. }
  65. }
  66.  
  67. Figure *makeFigure()
  68. {
  69. Figure *figure = malloc(sizeof(Figure));
  70. scanf("%d", &figure->numPoints);
  71. figure->points = malloc(sizeof(Vector) * figure->numPoints);
  72. for (int i = 0; i < figure->numPoints; i++)
  73. {
  74. scanf("(%lf, %lf, %lf)", &figure->points[i].x, &figure->points[i].y, &figure->points[i].z);
  75. }
  76. scanf("%d", &figure->numMeshes);
  77. figure->meshes = malloc(sizeof(Mesh) * figure->numMeshes);
  78. for (int i = 0; i < figure->numMeshes; i++)
  79. {
  80. scanf("(%d, %d, %d)", &figure->meshes[i].a, &figure->meshes[i].b, &figure->meshes[i].c);
  81. }
  82. setBoundary(figure);
  83. return figure;
  84. }
  85.  
  86. void freeFigure(Figure *figure)
  87. {
  88. free(figure->points);
  89. free(figure->meshes);
  90. for (int i = 0; i < figure->numPoints; i++)
  91. {
  92. free(figure->boundary[i]);
  93. }
  94. free(figure->boundary);
  95. free(figure);
  96. }
  97.  
  98. int isOriented(Figure *figure)
  99. {
  100. for (int i = 0; i < figure->numPoints; i++)
  101. {
  102. for (int j = 0; j < figure->numPoints; j++)
  103. {
  104. if (figure->boundary[i][j] >= 2)
  105. {
  106. return 0;
  107. }
  108. }
  109. }
  110. return 1;
  111. }
  112.  
  113. int isClosed(Figure *figure)
  114. {
  115. if (!isOriented(figure))
  116. {
  117. return 0;
  118. }
  119. else
  120. {
  121. for (int i = 0; i < figure->numPoints; i++)
  122. {
  123. for (int j = 0; j < figure->numPoints; j++)
  124. {
  125. if (figure->boundary[i][j] && !figure->boundary[j][i])
  126. {
  127. return 0;
  128. }
  129. }
  130. }
  131. return 1;
  132. }
  133. }
  134.  
  135. double calculateArea(Figure *figure)
  136. {
  137. double area = 0.0;
  138. for (int i = 0; i < figure->numMeshes; i++)
  139. {
  140. Vector v1 = subtract(figure->points[figure->meshes[i].b], figure->points[figure->meshes[i].a]);
  141. Vector v2 = subtract(figure->points[figure->meshes[i].c], figure->points[figure->meshes[i].a]);
  142. Vector v = cross(v1, v2);
  143. area += sqrt(dot(v, v)) / 2;
  144. }
  145. return area;
  146. }
  147.  
  148. double calculatePerimeter(Figure *figure)
  149. {
  150. double perimeter = 0.0;
  151. for (int i = 0; i < figure->numPoints; i++)
  152. {
  153. for (int j = 0; j < figure->numPoints; j++)
  154. {
  155. if (figure->boundary[i][j] == 1 && figure->boundary[j][i] != 1)
  156. {
  157. Vector v = subtract(figure->points[i], figure->points[j]);
  158. perimeter += sqrt(dot(v, v));
  159. }
  160. }
  161. }
  162. return perimeter;
  163. }
  164.  
  165. double calculateVolume(Figure *figure)
  166. {
  167. double volume = 0.0;
  168. for (int i = 0; i < figure->numMeshes; i++)
  169. {
  170. Vector v1 = figure->points[figure->meshes[i].a];
  171. Vector v2 = figure->points[figure->meshes[i].b];
  172. Vector v3 = figure->points[figure->meshes[i].c];
  173. volume += dot(v1, cross(v2, v3)) / 6;
  174. }
  175. if (volume < 0)
  176. {
  177. volume = -volume;
  178. }
  179. return volume;
  180. }
  181.  
  182. void printDetails(Figure *figure)
  183. {
  184. if (isOriented(figure))
  185. {
  186. if (isClosed(figure))
  187. {
  188. printf("closed and oriented\n");
  189. printf("volume : %lf\n", calculateVolume(figure));
  190. printf("area : %lf\n", calculateArea(figure));
  191. return;
  192. }
  193. else
  194. {
  195. printf("oriented\n");
  196. }
  197. }
  198. else
  199. {
  200. printf("unoriented\n");
  201. }
  202. printf("area : %lf\n", calculateArea(figure));
  203. printf("perimeter: %lf\n", calculatePerimeter(figure));
  204. }
  205.  
  206. int main()
  207. {
  208. Figure *figure = makeFigure();
  209. printDetails(figure);
  210. freeFigure(figure);
  211. return 0;
  212. }
Success #stdin #stdout 0.01s 5316KB
stdin
4
(0.0, 0.0, 0.0)
(1.0, 0.0, 0.0)
(0.0, 1.0, 0.0)
(0.0, 0.0, 1.0)
4
(0, 2, 1)
(0, 1, 3)
(0, 3, 2)
(1, 2, 3)
stdout
closed and oriented
volume : 0.166667
area   : 2.366025