File: Shape.h

package info (click to toggle)
veroroute 2.38-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,044 kB
  • sloc: cpp: 21,512; xml: 89; sh: 65; lisp: 20; makefile: 5
file content (258 lines) | stat: -rw-r--r-- 9,353 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*
	VeroRoute - Qt based Veroboard/Perfboard/PCB layout & routing application.

	Copyright (C) 2017  Alex Lawrow    ( dralx@users.sourceforge.net )

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "MyRGB.h"

// Class to describe a simple shape (e.g. for drawing component outlines)

enum class SHAPE { LINE = 0, RECT, ROUNDED_RECT, ELLIPSE, ARC, CHORD };

class Shape : public Persist
{
public:
	Shape(SHAPE type = SHAPE::RECT, bool bLine = true, bool bFill = false, double x1 = 0, double x2 = 0, double y1 = 0, double y2 = 0, double a3 = 0)
	: m_type(type)
	, m_x1(x1), m_x2(x2)
	, m_y1(y1), m_y2(y2)
	, m_a1(0), m_a2(90), m_a3(a3)
	, m_bDrawLine(bLine)
	, m_bDrawFill(bFill)
	, m_lineColor(0x000000)
	, m_fillColor(0x00FF00)	// Green
	{
	}
	Shape(SHAPE type, bool bLine, bool bFill, double x1, double x2, double y1, double y2, double a1, double a2, double a3 = 0)
	: m_type(type)
	, m_x1(x1), m_x2(x2)
	, m_y1(y1), m_y2(y2)
	, m_a1(a1), m_a2(a2), m_a3(a3)
	, m_bDrawLine(bLine)
	, m_bDrawFill(bFill)
	, m_lineColor(0x000000)
	, m_fillColor(0x00FF00)	// Green
	{
	}
	Shape(const Shape& o) { *this = o; }
	virtual ~Shape() {}
	Shape& operator=(const Shape& o)
	{
		m_type		= o.m_type;
		m_x1		= o.m_x1;	m_x2 = o.m_x2;
		m_y1		= o.m_y1;	m_y2 = o.m_y2;
		m_a1		= o.m_a1;	m_a2 = o.m_a2;	m_a3 = o.m_a3;
		m_bDrawLine	= o.m_bDrawLine;
		m_bDrawFill	= o.m_bDrawFill;
		m_lineColor	= o.m_lineColor;
		m_fillColor	= o.m_fillColor;
		return *this;
	}
	bool operator==(const Shape& o) const	// Compare persisted info
	{
		return m_type		 == o.m_type
			&& m_x1 - o.m_x1 == 0.0		&& m_x2 - o.m_x2 == 0.0
			&& m_y1	- o.m_y1 == 0.0		&& m_y2	- o.m_y2 == 0.0
			&& m_a1	- o.m_a1 == 0.0		&& m_a2	- o.m_a2 == 0.0		&& m_a3	- o.m_a3 == 0.0
			&& m_bDrawLine	 == o.m_bDrawLine
			&& m_bDrawFill	 == o.m_bDrawFill
			&& m_lineColor	 == o.m_lineColor
			&& m_fillColor	 == o.m_fillColor;
	}
	bool operator!=(const Shape& o) const
	{
		return !(*this == o);
	}
	bool operator<(const Shape& o) const	// For determining render order
	{
		if ( m_bDrawLine	!= o.m_bDrawLine )	return !m_bDrawLine;	// Prefer no line
		if ( m_bDrawFill	!= o.m_bDrawFill )	return m_bDrawFill;		// Prefer fill
		if ( m_lineColor	!= o.m_lineColor )	return m_lineColor < o.m_lineColor;
		if ( m_fillColor	!= o.m_fillColor )	return m_fillColor < o.m_fillColor;
		if ( m_type			!= o.m_type )		return static_cast<int>(m_type) < static_cast<int>(o.m_type);
		if ( m_x1 - o.m_x1	!= 0.0 )			return m_x1 < o.m_x1;
		if ( m_x2 - o.m_x2	!= 0.0 )			return m_x2 < o.m_x2;
		if ( m_y1 - o.m_y1	!= 0.0 )			return m_y1 < o.m_y1;
		if ( m_y2 - o.m_y2	!= 0.0 )			return m_y2 < o.m_y2;
		if ( m_a1 - o.m_a1	!= 0.0 )			return m_a1 < o.m_a1;
		if ( m_a2 - o.m_a2	!= 0.0 )			return m_a2 < o.m_a2;
		return m_a3 < o.m_a3;
	}
	void SetType(SHAPE c)				{ m_type = c; }
	void SetX1(double d)				{ m_x1 = d; }
	void SetX2(double d)				{ m_x2 = d; }
	void SetY1(double d)				{ m_y1 = d; }
	void SetY2(double d)				{ m_y2 = d; }
	void SetA1(double d)				{ m_a1 = d; }
	void SetA2(double d)				{ m_a2 = d; }
	void SetA3(double d)				{ m_a3 = d; }
	void SetDrawLine(bool b)			{ m_bDrawLine = b; }
	void SetDrawFill(bool b)			{ m_bDrawFill = b; }
	void SetLineColor(const MyRGB& r)	{ m_lineColor = r; }
	void SetFillColor(const MyRGB& r)	{ m_fillColor = r; }
	void Set(double x1, double x2,
			 double y1, double y2,
			 double a1, double a2, double a3)
	{
		m_x1 = x1;	m_x2 = x2;
		m_y1 = y1;	m_y2 = y2;
		m_a1 = a1;	m_a2 = a2;	m_a3 = a3;
	}

	void SetCX(double d)	{ Move(0, d - GetCX()); }
	void SetCY(double d)	{ Move(d - GetCY(), 0); }
	void SetDX(double d)	{ Expand( d - GetDX(), 0 ); }
	void SetDY(double d)	{ Expand( 0, d - GetDY() ); }
	void Move(double dDown, double dRight)
	{
		m_x1 += dRight;		m_x2 += dRight;
		m_y1 += dDown;		m_y2 += dDown;
	}
	void Expand(double dx, double dy)
	{
		m_x1 -= 0.5 * dx;	m_x2 += 0.5 * dx;
		m_y1 -= 0.5 * dy;	m_y2 += 0.5 * dy;
	}
	const SHAPE&	GetType() const			{ return m_type; }
	const double&	GetX1() const			{ return m_x1; }
	const double&	GetX2() const			{ return m_x2; }
	const double&	GetY1() const			{ return m_y1; }
	const double&	GetY2() const			{ return m_y2; }
	const double&	GetA1() const			{ return m_a1; }
	const double&	GetA2() const			{ return m_a2; }
	const double&	GetA3() const			{ return m_a3; }
	const bool&		GetDrawLine() const		{ return m_bDrawLine; }
	const bool&		GetDrawFill() const		{ return m_bDrawFill; }
	const MyRGB&	GetLineColor() const	{ return m_lineColor; }
	const MyRGB&	GetFillColor() const	{ return m_fillColor; }
	const double&	GetXmin() const			{ return std::min(m_x1, m_x2); }
	const double&	GetXmax() const			{ return std::max(m_x1, m_x2); }
	const double&	GetYmin() const			{ return std::min(m_y1, m_y2); }
	const double&	GetYmax() const			{ return std::max(m_y1, m_y2); }
	double			GetCX() const			{ return 0.5 * ( m_x1 + m_x2 ); }
	double			GetCY() const			{ return 0.5 * ( m_y1 + m_y2 ); }
	double			GetDX() const			{ return m_x2 - m_x1; }
	double			GetDY() const			{ return m_y2 - m_y1; }
	double			GetXlen() const			{ return fabs(GetDX()); }
	double			GetYlen() const			{ return fabs(GetDY()); }
	double			GetAlen() const			{ double d = m_a2 - m_a1; while ( d < 0 ) d += 360.0; return d; }
	void GetSafeBounds(double& L, double& R, double& T, double& B) const	// Allows for worst case rotation "A3"
	{
		if ( GetA3() == 0.0 )
		{
			L = GetXmin();		R = GetXmax();
			T = GetYmin();		B = GetYmax();
		}
		else
		{
			// The following could be improved (to a tighter bound) by considering the shape and rotation angle
			const double DX( GetDX() ), DY( GetDY() );
			const double d = sqrt(DX*DX + DY*DY) * 0.5;
			L = GetCX() - d;	R = GetCX() + d;
			T = GetCY() - d;	B = GetCY() + d;
		}
	}
	// Persist interface functions
	virtual void Load(DataStream& inStream) override
	{
		int type(0);
		inStream.Load(type);
		m_type = static_cast<SHAPE>(type);
		inStream.Load(m_x1);
		inStream.Load(m_x2);
		inStream.Load(m_y1);
		inStream.Load(m_y2);
		inStream.Load(m_a1);
		inStream.Load(m_a2);
		if ( inStream.GetVersion() >= VRT_VERSION_29 )
		{
			inStream.Load(m_a3);		// Added in VRT_VERSION_29
			inStream.Load(m_bDrawLine);	// Added in VRT_VERSION_29
			inStream.Load(m_bDrawFill);	// Added in VRT_VERSION_29
			m_lineColor.Load(inStream);	// Added in VRT_VERSION_29
			m_fillColor.Load(inStream);	// Added in VRT_VERSION_29
		}
		else
		{
			m_a3		= 0;
			m_bDrawLine	= true;
			m_bDrawFill	= false;
			m_lineColor.SetRGB(0,0,0);
			m_fillColor.SetRGB(0,255,0);	// Green
		}
	}
	virtual void Save(DataStream& outStream) override
	{
		outStream.Save(static_cast<int>(m_type));
		outStream.Save(m_x1);
		outStream.Save(m_x2);
		outStream.Save(m_y1);
		outStream.Save(m_y2);
		outStream.Save(m_a1);
		outStream.Save(m_a2);
		outStream.Save(m_a3);			// Added in VRT_VERSION_29
		outStream.Save(m_bDrawLine);	// Added in VRT_VERSION_29
		outStream.Save(m_bDrawFill);	// Added in VRT_VERSION_29
		m_lineColor.Save(outStream);	// Added in VRT_VERSION_29
		m_fillColor.Save(outStream);	// Added in VRT_VERSION_29
	}
	static const std::map<SHAPE, std::string>& GetMapShapeStrings()
	{
		static std::map<SHAPE, std::string>	mapShapeToStr;
		if ( mapShapeToStr.empty() )
		{
			mapShapeToStr[SHAPE::LINE]			= "Line";
			mapShapeToStr[SHAPE::RECT]			= "Rectangle";
			mapShapeToStr[SHAPE::ROUNDED_RECT]	= "Rounded Rectangle";
			mapShapeToStr[SHAPE::ELLIPSE]		= "Ellipse";
			mapShapeToStr[SHAPE::ARC]			= "Arc";
			mapShapeToStr[SHAPE::CHORD]			= "Chord";
		}
		return mapShapeToStr;
	}
	static const std::list<std::string>& GetListShapeStrings()
	{
		static std::list<std::string>	listShapeStr;	// Use for populating combo boxes
		if ( listShapeStr.empty() )
		{
			listShapeStr.push_back("Line");
			listShapeStr.push_back("Rectangle");
			listShapeStr.push_back("Rounded Rectangle");
			listShapeStr.push_back("Ellipse");
			listShapeStr.push_back("Arc");
			listShapeStr.push_back("Chord");
		}
		return listShapeStr;
	}
private:
	// Data (x1,y1) and (x2,y2) are either
	// the start and end points of a line, or the TL and BR corners of a rectangle.
	// Ellipses fit to the rectangle.
	// An arc is a CCW part of the ellipse, starting at "a1" and ending at "a2".
	// Note the angle is w.r.t. a circle rather than an ellipse.
	// The angle "a3" can be used to provide a final CCW rotation of the shape about its centre.
	SHAPE	m_type;
	double	m_x1, m_x2;			// Units of 100 mil w.r.t. footprint centre
	double	m_y1, m_y2;			// Units of 100 mil w.r.t. footprint centre
	double	m_a1, m_a2, m_a3;	// Angles measured CCW degrees.  Zero at 3 o'clock.
	bool	m_bDrawLine;		// Draw line (can only be false if m_bFill is true)
	bool	m_bDrawFill;		// Fill with color
	MyRGB	m_lineColor;		// Line color.	Always black
	MyRGB	m_fillColor;		// Fill color.
};