如何存储我的项目数据,以便以多种方式进行通信?

huangapple go评论59阅读模式
英文:

How to store data for my project that needs to communicate in multiple ways?

问题

I am trying to store the data for walls in a room and the ceiling planes. The user draws the outline of a building with 2D lines. Each line represents a wall. Then, if the roof is not flat, they might draw out dashed lines which represent where ceiling planes will connect.

So here are some things to keep in mind:
The user will change the pitch of the respected ceiling plane (in the image alpha 1 is the pitch of ceiling plane A). The user can also change the height of the rectangular wall (if it hinges off a ceiling plane) through the ceiling plane. I ultimately am trying to get the area of each wall and from the image, one wall is simply calculate by finding the area of a rectangle, the other is much more complicated. If I change the height of a rectangle wall, it indirectly changes the area of the pentagon wall. If I change the alpha value of a ceiling plane, then that also changes the area of the pentagon wall. The wall class is similar to an edge in a graph. The walls are also being stored in a vector of abstract Wall pointers that way I can utilize virtual methods.

I created an abstract wall class (interface) that a SquareWall class and PentagonWall class inherit from.

class Wall {
	protected:
		int Prev;
		int Next;
		int Orientation;
		int isHinged;
	public:
		// Constructors
                ...

		virtual ~Wall() = 0;

		// Setters
		...

		// Getters
		...

		// Pure Virtual Functions
		virtual void setHeight(int newHeight)  = 0;
		virtual void setLength(int newLength)  = 0;
		virtual int getArea() const = 0;
		virtual int getHeight() const = 0;
		virtual int getLength() const = 0;
	};
class PentagonWall : public Wall {
	private:
		Quadrilateral* Quad1;
		Quadrilateral* Quad2;

	public:
		// Constructors
                ...

		~PentagonWall();

		void setHeight(int newHeight) override {}
		void setLength(int newLength)  override {}
		int getArea() const override { 
                    return this->Quad1->getArea() + this->Quad2->getArea();
                }
		int getHeight() const override { return -1; }
		int getLength() const override { 
                    return this->Quad1->rect.Length + this->Quad2->rect.Length;
                }

		Quadrilateral* getQuad1() { return this->Quad1; }
		Quadrilateral* getQuad2() { return this->Quad2; }
	};
class RectangleWall : public Wall {
	private:
		Rectangle* Square;
	public:
		RectangleWall();
		RectangleWall(int prev, int next);
		~RectangleWall();
		void setHeight(int newHeight) override { 
            this->Square.Height = newHeight;
        }
		void setLength(int newLength)  override {
            this->Square.Length = newLength;
        }
		int getArea() const override {
            return this->Square.Height * this->Square.Length;
        }
		int getHeight() const override {
            return this->Square.Height;
        }
		int getLength() const override {
            return this->Square.Length;
        }
	};

Here is the code for the shape classes:

struct Shape {
        Shape() {}
        virtual int getArea() = 0;
    };

    struct Ceiling : Shape {
        int Orientation;
        int Pitch;
        int FootPrintArea;
        Ceiling() : Orientation(0), Pitch(0), FootPrintArea(0) {}
        Ceiling(int initOri, int initPitch, int initFPArea) : Orientation(initOri), Pitch(initPitch), FootPrintArea(initFPArea){}
        int getArea() override {
            if (Pitch == 0) return this->FootPrintArea;
            return this->FootPrintArea * OtEnum::PITCH_TO_MULTIPLIER[this->Pitch];
        }
    };

    struct Rectangle : Shape {
        int Length;
        int Height;

        // Constructors
        ...

        int getArea() override {
            return this->Length * this->Height;
        }
    };

    struct Triangle : Shape {
        int Base;
        int Height;

        // Constructors
        ...

        int getArea() override {
            return (this->Base * this->Height) / 2;
        }
    };

    struct Quadrilateral : Shape {
        Rectangle rect;
        Triangle tri;
        Quadrilateral() : rect(0, 0), tri(0, 0) {}
        Quadrilateral(Rectangle newRect, Triangle newTri) : 
                rect(newRect.Length, newRect.Height), tri(newTri.Base, newTri.Height) {} 

        int getArea() override {
            return rect.getArea() + tri.getArea();
        }
    };

And here is the roof class:

struct Roof {
        Ceiling* Ceil;
        
        Wall* HingeWall;

        Quadrilateral* Quad1;
        Quadrilateral* Quad2;

        Rectangle* BackRect;
        Wall* BackWall;

        Roof(Wall* newHingeWall);
        Roof();
    };

Heres a brief explanation of how my solution works:
Each roof technically has walls that it lays on top of in the two-dimensional drawing. I use that to determine the lengths of the quadrilaterals that the roof will then point to. When a roofs pitch is updated, the corresponding quadrilaterals (if there not nullptrs) will have their triangle height updated. When the roofs hinge height is updated, the corresponding quadrilaterals will have their square heights updated. This way it works O(1), I don't have to do any searching except initially to setup the pointers in the Roof class.
Here is also an illustration for how this works. Roof Structure Illustration

I assign the HingeWall, Quad1, Quad2, and BackWall by looping through a ceiling plane and using conditions such as if a line is on top of another line and if the wall that we are on is hinged or not. I could find a slightly better way to make those assignments but that's not my current problem. Although everything here technically works, it is not very pretty and I feel as if it is simply bad design. Hopefully someone has something that can help me and if any additional information is needed then I can add it to this post.

英文:

I am trying to store the data for walls in a room and the ceiling planes. The user draws the outline of a building with 2D lines. Each line represents a wall. Then, if the roof is not flat, they might draw out dashed lines which represent where ceiling planes will connect. I have an illustration that should help a lot with my explanations.Gable Roof Drawing

So here are some things to keep in mind:
The user will change the pitch of the respected ceiling plane (in the image alpha 1 is the pitch of ceiling plane A). The user can also change the height of the rectangular wall (if it hinges off a ceiling plane) through the ceiling plane. I ultimately am trying to get the area of each wall and from the image, one wall is simply calculate by finding the area of a rectangle, the other is much more complicated. If I change the height of a rectangle wall, it indirectly changes the area of the pentagon wall. If I change the alpha value of a ceiling plane, then that also changes the area of the pentagon wall. The wall class is similar to an edge in a graph. The walls are also being stored in a vector of abstract Wall pointers that way I can utilize virtual methods.

I created an abstract wall class (interface) that a SquareWall class and PentagonWall class inherit from.

class Wall {
	protected:
		int Prev;
		int Next;
		int Orientation;
		int isHinged;
	public:
		// Constructors
                ...

		virtual ~Wall() = 0;

		// Setters
		...

		// Getters
		...

		// Pure Virtual Functions
		virtual void setHeight(int newHeight)  = 0;
		virtual void setLength(int newLength)  = 0;
		virtual int getArea() const = 0;
		virtual int getHeight() const = 0;
		virtual int getLength() const = 0;
	};
class PentagonWall : public Wall {
	private:
		Quadrilateral* Quad1;
		Quadrilateral* Quad2;

	public:
		// Constructors
                ...

		~PentagonWall();

		void setHeight(int newHeight) override {}
		void setLength(int newLength)  override {}
		int getArea() const override { 
                    return this->Quad1->getArea() + this->Quad2>getArea();
                }
		int getHeight() const override { return -1; }
		int getLength() const override { 
                    return this->Quad1->rect.Length + this->Quad2->rect.Length;
                }

		Quadrilateral* getQuad1() { return this->Quad1; }
		Quadrilateral* getQuad2() { return this->Quad2; }
	};
class RectangleWall : public Wall {
	private:
		Rectangle* Square;
	public:
		RectangleWall();
		RectangleWall(int prev, int next);
		~RectangleWall();
		void setHeight(int newHeight) override { 
            this->Square.Height = newHeight;
        }
		void setLength(int newLength)  override {
            this->Square.Length = newLength;
        }
		int getArea() const override {
            return this->Square.Height * this->Square.Length;
        }
		int getHeight() const override {
            return this->Square.Height;
        }
		int getLength() const override {
            return this->Square.Length;
        }
	};

Here is the code for the shape classes:

struct Shape {
        Shape() {}
        virtual int getArea() = 0;
    };

    struct Ceiling : Shape {
        int Orientation;
        int Pitch;
        int FootPrintArea;
        Ceiling() : Orientation(0), Pitch(0), FootPrintArea(0) {}
        Ceiling(int initOri, int initPitch, int initFPArea) : Orientation(initOri), Pitch(initPitch), FootPrintArea(initFPArea){}
        int getArea() override {
            if (Pitch == 0) return this->FootPrintArea;
            return this->FootPrintArea * OtEnum::PITCH_TO_MULTIPLIER[this->Pitch];
        }
    };

    struct Rectangle : Shape {
        int Length;
        int Height;

        // Constructors
        ...

        int getArea() override {
            return this->Length * this->Height;
        }
    };

    struct Triangle : Shape {
        int Base;
        int Height;

        // Constructors
        ...

        int getArea() override {
            return (this->Base * this->Height) / 2;
        }
    };

    struct Quadrilateral : Shape {
        Rectangle rect;
        Triangle tri;
        Quadrilateral() : rect(0, 0), tri(0, 0) {}
        Quadrilateral(Rectangle newRect, Triangle newTri) : 
                rect(newRect.Length, newRect.Height), tri(newTri.Base, newTri.Height) {} 

        int getArea() override {
            return rect.getArea() + tri.getArea();
        }
    };

And here is the roof class:

struct Roof {
        Ceiling* Ceil;
        
        Wall* HingeWall;

        Quadrilateral* Quad1;
        Quadrilateral* Quad2;

        Rectangle* BackRect;
        Wall* BackWall;

        Roof(Wall* newHingeWall);
        Roof();
    };

Heres a brief explanation of how my solution works:
Each roof technically has walls that it lays on top of in the two-dimensional drawing. I use that to determine the lengths of the quadrilaterals that the roof will then point to. When a roofs pitch is updated, the corresponding quadrilaterals (if there not nullptrs) will have their triangle height updated. When the roofs hinge height is updated, the corresponding quadrilaterals will have their square heights updated. This way it works O(1), I don't have to do any searching except initially to setup the pointers in the Roof class.
Here is also an illustration for how this works. Roof Structure Illustration

I assign the HingeWall, Quad1, Quad2, and BackWall by looping through a ceiling plane and using conditions such as if a line is on top of another line and if the wall that we are on is hinged or not. I could find a slightly better way to make those assignments but that's not my current problem. Although everything here technically works, it is not very pretty and I feel as if it is simply bad design. Hopefully someone has something that can help me and if any additional information is needed then I can add it to this post.

答案1

得分: 1

我认为你正在陷入对象导向编程的陷阱,将问题中的所有名词都划线,然后将每个名词变成一个类(我记得在课堂练习中确实有这样的事情)。这对于管理客户、订单和账户等业务软件有时是个好主意,但你并不是在写那种软件 - 你正在编写一个数学计算程序。

我建议针对这种类型的问题采取的方法是停止过于关注名词。删除所有这些结构和类。相反,首先解决问题的数学部分,然后将数学编程到计算机中。

我不确定我是否完全理解了问题,所以我不会提供公式,但看起来你想让用户输入 L1、L2、h1 和 alpha,然后计算机将计算 h2,然后使用所有这些来计算你感兴趣的墙面积,并显示出来。

不要过于复杂化程序。只需告诉计算机执行实际需要的最低限度的操作。保持简单。

英文:

I think you are falling for object orientation disease where you underline all the nouns in the question and then make each noun a class (this is a real thing I remember doing in a classroom exercise). This is sometimes a good idea for business software that manages customers and orders and accounts, but you are not writing that - you are writing a mathematical calculation program.

The approach I recommend for this type of problem is to stop obsessing about nouns. Delete all those structs and classes. Instead, work out the mathematics of the problem first, and then program the mathematics into the computer.

I'm not sure I understood the problem perfectly so I won't give formulas, but it looks like you want to get the user to type in L1, L2, h1, and alpha, and then the computer will calculate h2 and then use all of these to calculate the wall area that you are interested in, and display that.

Don't overcomplicate the program. Just tell the computer to do the bare minimum that you actually need the computer to do. KISS.

huangapple
  • 本文由 发表于 2023年6月8日 06:42:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76427522.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定