Vous pouvez vous restructurer les classes un peu, mais il faudrait une autre classe indépendante. Vous pouvez créer un ensemble de classes de vecteurs mathématiques 2D et 3D, mais vous devez avoir tous les opérateurs surchargés et les fonctions mathématiques que les vecteurs peuvent faire comme ajouter, soustraire, multiplier par vecteur ou par scalaire et si par vecteur vous avez le point et le produit croisé à s'inquiéter. Vous auriez besoin de normaliser les méthodes, la longueur et autres. Une fois que vous avez ces classes de vecteur de mathématiques de travail. Ensuite, vous pouvez redessiner vos classes de formes en utilisant les vecteurs à la place. Ou bien, au lieu d'écrire votre propre classe de vecteurs, vous pouvez utiliser une classe de bibliothèque mathématique telle que la bibliothèque mathématique de GLM utilisée pour travailler dans OpenGL. C'est gratuit et open source et c'est aussi une bibliothèque en-tête seulement. Une fois que vous avez installé la bibliothèque sur un chemin, tout ce que vous devez faire est d'inclure son en-tête. Vous n'avez pas à vous soucier de la liaison. Puis, avec ces classes de vecteurs, il ferait le calcul dans vos classes de forme plus facile à faire, et il serait plus facile de concevoir les classes de forme: Voici un exemple de ce code de pseudo ressemblerait à ceci:
#include <glm\glm.hpp>
// Needed If Doing Matrix Transformations: Rotation, Translation Scaling etc.
// #include <glm\gtc\matrix_transform.hpp>
class Shape {
public:
enum Type {
NONE = 0,
TRIANGLE,
SQUARE,
CIRCLE,
};
protected:
Type type_;
glm::vec4 color_ { 1.0f, 1.0f, 1.0f, 1.0f }; // Initialize List Set To White By Default
double perimeter_; // Also Circumference for Circle
double area_;
// double volume_; // If in 3D.
public:
// Default Constructor
Shape() : type_(NONE), color_(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)) {}
// User Defined Constructors
// Sets Shape Type Only Color Is Optional & By Default Is White
explicit Shape(Type type, glm::vec4 color = glm::vec4()) : type_(type), color_(color) {}
Type getType() const { return type_; }
void setType(Shape::Type type) {
if (type_ == NONE) {
// Its okay to set a new shape type
type_ = type;
}
// We Already Have a Defined Shape
return;
}
// Getters That Are Commonly Found Across All Shapes
double getPerimeter() const { return perimeter_; }
double getArea() const { return area_; }
// Common Functions that can be done to any shape
void setSolidColor(glm::vec4 color) { color_ = color };
glm::vec4 getColor() const { return color; }
// Common Interface That All Shapes Share But Must Override
virtual double calculateArea() = 0;
virtual double calculatePerimeter() = 0;
// Since we do not know what kind of shape to modify until we have one
// to work with, we do not know how many parameters this function will need.
// To get around this we can use a function template and then have overloads
// for each type we support
template<typename Type = Shape>
virtual void modify(Type* pShape /*,glm::vec3... params*/);
// Overloaded Types: - Should Be Defined & Overridden By the Derived Class
virtual void modify<Triangle>(Triangle* pTriangle, glm::vec3, glm::vec3, glm::vec3, glm::vec4 = glm::vec4()) { /* ... */ }
virtual void modify<Circle>(Cirlce* pCircle, float radius, glm::vec4 color = glm::vec4()) { /* ... */}
};
Ensuite, un hérité la classe ressemblerait à quelque chose comme:
class Triangle : public Shape {
public:
// Could Be An Option To Where This is a base class as well to specific types of triangles:
enum TriangleType {
Acute = 0,
Right,
Equilateral,
Obtuse
} // then each of these would have properties specific to each type
private:
glm::vec3[3] vertices_;
public:
// Default Constructor
Triangle() : Shape(TRIANGLE) {} // Sets The Shape Type But Has No Vertices Or Area; just default construction
// Vertices But No Color
Triangle(glm::vec3 A, glm::vec3 B, glm::vec3 C) : Shape(TRIANGLE) {
vertices_[0] = A;
vertices_[1] = B;
vettices_[2] = C;
// Call These To Have These Values
calculatePerimeter();
calculateArea();
}
// Vertices & Color
Triangle(glm::vec3 A, glm::vec3 B, glm::vec3 C, glm::vec4 color) : Shape(TRIANGLE) {
vertices_[0] = A;
vertices_[1] = B;
vertices_[2] = C;
calculatePerimeter();
calculateArea();
}
// No Need To Do The Set & Get Colors - Base Class Does that for you.
// Methods that this shape must implement
virtual double calculateArea() override {
// Calculations For Getting Area of A Triangle
area_ = /* calculation */;
};
virtual double calculatePerimeter() override {
// Calculations For Getting Perimeter of A Triangle
perimeter_ = /* calculation */;
};
void modify<Triangle>(Triangle* pTriangle, glm::vec3, glm::vec3, glm::vec3, glm::vec4 = glm::vec4()) override { /* ... */ }
};
Maintenant comme pour afficher l'information; Personnellement, je ne mettrais pas en œuvre dans ces classes. Il suffit d'utiliser votre niveau std::cout
ou std::ofstream
etc. pour imprimer les valeurs à l'écran ou simplement acheter fichier en utilisant le getters
comme celui-ci:
#include <iostream>
#include "Triangle.h"
int main() {
Triangle t1(glm::vec3(0.0f, 1.0f, -1.3f), // Vertex A
glm::vec3(3.2f, 5.5f, -8.9f), // B
glm::vec3(-4.5f, 7.6f, 8.2f), // C
glm::vec4(0.8f, 0.9f, 0.23f, 1.0f)); // Color
std::cout << "Perimeter is " << t1.getPerimeter() << std::endl;
std::cout << "Area is " << t1.getArea() << std::endl;
return 0;
}
Je ne l'ai jamais entendu parler est-comme-un. Comment définiriez-vous cette relation? –
"fonction modifyShape où chaque paramètre de la forme est modifié en fonction du paramètre de l'utilisateur" Cela ne ressemble pas à une exigence bien indiquée. Qu'est-ce que "basé sur le paramètre de l'utilisateur" signifie exactement? Si l'utilisateur entre 5, et que nous avons un triangle unitaire en (7, 8) et un cercle d'unité centré en (1, -2), quel est le résultat attendu? –