1 /***************************************************************************
2  * canvas.h is part of Math Graphic Library
3  * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru>       *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License  as       *
7  *   published by the Free Software Foundation; either version 3 of the    *
8  *   License, or (at your option) any later version.                       *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Lesser General Public     *
16  *   License along with this program; if not, write to the                 *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifndef MGL_CANVAS_H
21 #define MGL_CANVAS_H
22 #include "mgl2/base.h"
23 //-----------------------------------------------------------------------------
24 struct GifFileType;
25 //-----------------------------------------------------------------------------
26 /// Structure for drawing axis and ticks
27 struct MGL_EXPORT mglAxis
28 {
mglAxismglAxis29 	mglAxis() : dv(0),ds(0),d(0),ns(0),	v0(0),v1(0),v2(0),o(NAN),	f(0),	ch(0),	pos('t'),sh(0),inv(false),angl(NAN)	{}
mglAxismglAxis30 	mglAxis(const mglAxis &aa) : dv(aa.dv),ds(aa.ds),d(aa.d),ns(aa.ns),	t(aa.t),fact(aa.fact),stl(aa.stl),	dir(aa.dir),a(aa.a),b(aa.b),org(aa.org), v0(aa.v0),v1(aa.v1),v2(aa.v2),o(aa.o),	f(aa.f),txt(aa.txt),	ch(aa.ch),	pos(aa.pos),sh(aa.sh),inv(aa.inv),angl(aa.angl)	{}
31 #if MGL_HAVE_RVAL
mglAxismglAxis32 	mglAxis(mglAxis &&aa) : dv(aa.dv),ds(aa.ds),d(aa.d),ns(aa.ns),	t(aa.t),fact(aa.fact),stl(aa.stl),	dir(aa.dir),a(aa.a),b(aa.b),org(aa.org), v0(aa.v0),v1(aa.v1),v2(aa.v2),o(aa.o),	f(aa.f),txt(aa.txt),	ch(aa.ch),	pos(aa.pos),sh(aa.sh),inv(aa.inv),angl(aa.angl)	{}
33 #endif
34 
35 	const mglAxis &operator=(const mglAxis &aa)
36 	{	dv=aa.dv; ds=aa.ds; d=aa.d; ns=aa.ns; t=aa.t; fact=aa.fact; stl=aa.stl;
37 		dir=aa.dir; a=aa.a; b=aa.b; org=aa.org; v0=aa.v0; v1=aa.v1; v2=aa.v2; o=aa.o;
38 		f=aa.f; txt=aa.txt; 	ch=aa.ch; pos=aa.pos; sh=aa.sh; inv=aa.inv;	return aa;	}
AddLabelmglAxis39 	inline void AddLabel(const std::wstring &lbl, mreal v)
40 	{	if(mgl_isfin(v))	txt.push_back(mglText(L' '+lbl+L' ',v));	}
ClearmglAxis41 	inline void Clear()
42 	{	dv=ds=d=v0=v1=v2=sh=0;	o=NAN;	ns=f=0;	pos = 't';	inv=false;
43 		fact.clear();	stl.clear();	t.clear();	txt.clear();	}
44 
45 	mreal dv,ds;	///< Actual step for ticks and subticks.
46 	mreal d;		///< Step for axis ticks (if positive) or its number (if negative).
47 	int ns;			///< Number of axis subticks.
48 	std::wstring t;	///< Tick template (set "" to use default one ("%.2g" in simplest case))
49 	std::wstring fact;	///< Factor which should be placed after number (like L"\pi")
50 	std::string stl;	///< Tick styles (default is ""=>"3m")
51 	mglPoint dir;	///< Axis direction
52 	mglPoint a,b;	///< Directions of over axis
53 	mglPoint org;
54 	mreal v0;		///< Center of axis cross section
55 	mreal v1;		///< Minimal axis range.
56 	mreal v2;		///< Maximal axis range.
57 	mreal o;		///< Point of starting ticks numbering (if NAN then Org is used).
58 	int f;			///< Flag 0x1 - time, 0x2 - manual, 0x4 - fixed dv
59 	std::vector<mglText> txt;	///< Axis labels
60 	char ch;		///< Character of axis (like 'x','y','z','c')
61 	char pos;		///< Text position ('t' by default, or 'T' for opposite)
62 	mreal sh;		///< Extra shift of ticks and axis labels
63 	bool inv;		///< Inverse automatic origin position
64 	mreal angl;		///< Manual for ticks rotation (if not NAN)
65 };
66 //-----------------------------------------------------------------------------
67 class mglCanvas;
68 /// Structure for drawing region
69 struct MGL_EXPORT mglDrawReg
70 {
mglDrawRegmglDrawReg71 	mglDrawReg() {	memset(this,0,sizeof(mglDrawReg));	}
mglDrawRegmglDrawReg72 	mglDrawReg(const mglDrawReg &aa) : PDef(aa.PDef),angle(aa.angle),ObjId(aa.ObjId),PenWidth(aa.PenWidth),pPos(aa.pPos) ,x1(aa.x1),x2(aa.x2),y1(aa.y1),y2(aa.y2)	{}
73 #if MGL_HAVE_RVAL
mglDrawRegmglDrawReg74 	mglDrawReg(mglDrawReg &&aa) : PDef(aa.PDef),angle(aa.angle),ObjId(aa.ObjId),PenWidth(aa.PenWidth),pPos(aa.pPos) ,x1(aa.x1),x2(aa.x2),y1(aa.y1),y2(aa.y2)	{}
75 #endif
copymglDrawReg76 	inline void copy(const mglPrim &p)
77 	{	PDef = p.n3;	pPos = p.s;	ObjId = p.id;	PenWidth=p.w;	angle = p.angl;
78 		if(p.type==2 || p.type==3) PDef = p.m;	}
79 	inline const mglDrawReg &operator=(const mglDrawReg &aa)
80 	{	PDef=aa.PDef;	angle=aa.angle;	ObjId=aa.ObjId;	PenWidth=aa.PenWidth;	pPos=aa.pPos;	x1=aa.x1;	x2=aa.x2;	y1=aa.y1;	y2=aa.y2;	return aa;	}
81 	union
82 	{
83 		uint64_t PDef;
84 		unsigned char m[8];
85 	};
86 	int angle;	///< mask rotation values in degrees
87 	int ObjId;
88 	mreal PenWidth, pPos;
89 	int x1,x2,y1,y2;
90 	void set(mglCanvas *gr, int nx, int ny, int m);
91 };
92 //-----------------------------------------------------------------------------
93 /// Structure contains everything for drawing
94 struct MGL_EXPORT mglDrawDat
95 {
mglDrawDatmglDrawDat96 	mglDrawDat() {}
mglDrawDatmglDrawDat97 	mglDrawDat(const mglDrawDat &aa) : Pnt(aa.Pnt),Prm(aa.Prm),Sub(aa.Sub),Ptx(aa.Ptx),Glf(aa.Glf),Txt(aa.Txt)	{}
98 #if MGL_HAVE_RVAL
mglDrawDatmglDrawDat99 	mglDrawDat(mglDrawDat &&aa) : Pnt(aa.Pnt),Prm(aa.Prm),Sub(aa.Sub),Ptx(aa.Ptx),Glf(aa.Glf),Txt(aa.Txt)	{}
100 #endif
101 	inline const mglDrawDat&operator=(const mglDrawDat &aa)
102 	{	Pnt=aa.Pnt;	Prm=aa.Prm;	Ptx=aa.Ptx;	Glf=aa.Glf;	Txt=aa.Txt;	Sub=aa.Sub;	return aa;	}
103 	mglStack<mglPnt>  Pnt;	///< Internal points
104 	mglStack<mglPrim> Prm;	///< Primitives (lines, triangles and so on) -- need for export
105 	std::vector<mglBlock> Sub;	///< InPlot regions
106 	std::vector<mglText> Ptx;	///< Text labels for mglPrim
107 	std::vector<mglGlyph> Glf;	///< Glyphs data
108 	std::vector<mglTexture> Txt;	///< Pointer to textures
109 };
110 #if defined(_MSC_VER)
111 MGL_EXTERN template class MGL_EXPORT std::vector<mglDrawDat>;
112 #endif
113 //-----------------------------------------------------------------------------
114 union mglRGBA	{	uint32_t c; unsigned char r[4];	};
115 //-----------------------------------------------------------------------------
116 /// Class contains all functionality for creating different mathematical plots
117 class MGL_EXPORT mglCanvas : public mglBase
118 {
119 friend struct mglPrim;
120 friend struct mglDrawReg;
121 public:
122 using mglBase::Light;
123 
124 	mglCanvas(int w=800, int h=600);
125 	virtual ~mglCanvas();
126 
127 	/// Set default parameter for plotting
128 	void DefaultPlotParam();
129 
130 	/// Set angle of view indepently from mglCanvas::Rotate()
131 	virtual void View(mreal tetx,mreal tetz,mreal tety=0);
132 	/// Zoom in or zoom out (if Zoom(0, 0, 1, 1)) a part of picture
133 	virtual void Zoom(mreal x1, mreal y1, mreal x2, mreal y2);
134 	/// Restore image after View() and Zoom()
Restore()135 	inline void Restore()	{	Zoom(0,0,1,1);	}
136 
137 	/// Clear transformation matrix.
138 	inline void Identity(bool rel=false)	{	InPlot(0,1,0,1,rel);	}
139 	inline void Identity(mglMatrix &M, bool rel=false)	{	InPlot(M,0,1,0,1,rel);	}
140 	/// Push transformation matrix into stack
141 	void Push();
142 	/// Set PlotFactor
SetPlotFactor(mreal val)143 	inline void SetPlotFactor(mreal val)
144 	{	if(val<=0)	{B.pf=1.55;	set(MGL_AUTO_FACTOR);}	else {B.pf=val;	clr(MGL_AUTO_FACTOR);}	}
145 	/// Get PlotFactor
GetPlotFactor()146 	inline mreal GetPlotFactor()	{	return B.pf;	}
147 	/// Pop transformation matrix from stack
148 	void Pop();
149 	/// Clear up the frame
150 	virtual void Clf(mglColor back=NC);
151 	virtual void Clf(const char *col);
152 
153 	/// Put further plotting in cell of stick rotated on angles tet, phi
154 	void StickPlot(int num, int i, mreal tet, mreal phi);
155 	/// Put further plotting in cell of stick sheared on sx, sy
156 	void ShearPlot(int num, int i, mreal sx, mreal sy, mreal xd, mreal yd);
157 	/// Put further plotting in some region of whole frame surface.
158 	inline void InPlot(mreal x1,mreal x2,mreal y1,mreal y2,bool rel=true)
159 	{	InPlot(B,x1,x2,y1,y2,rel);	}
160 	void InPlot(mreal x1,mreal x2,mreal y1,mreal y2, const char *style);
161 	void InPlot(mglMatrix &M,mreal x1,mreal x2,mreal y1,mreal y2,bool rel=true);
162 	/// Add title for current subplot/inplot
163 	void Title(const char *title,const char *stl="#",mreal size=-2);
164 	void Title(const wchar_t *title,const char *stl="#",mreal size=-2);
165 	/// Set aspect ratio for further plotting.
166 	void Aspect(mreal Ax,mreal Ay,mreal Az);
167 	/// Shear a further plotting.
168 	void Shear(mreal Sx,mreal Sy);
169 	/// Rotate a further plotting.
170 	void Rotate(mreal TetX,mreal TetZ,mreal TetY=0);
171 	/// Rotate a further plotting around vector {x,y,z}.
172 	void RotateN(mreal Tet,mreal x,mreal y,mreal z);
173 	/// Set perspective (in range [0,1)) for plot. Set to zero for switching off. Return the current perspective.
174 	void Perspective(mreal a, bool req=true)
175 	{	if(req)	persp = Bp.pf = a;	else	Bp.pf = persp?persp:fabs(a);	}
176 	/// Save parameters of current inplot
SaveInPlot()177 	inline void SaveInPlot()
178 	{	sB=B;	sW=inW, sH=inH, sZ=ZMin, sX=inX, sY=inY, sFF=font_factor;	}
179 	/// Use saved parameters as current inplot
LoadInPlot()180 	inline void LoadInPlot()
181 	{	B=sB;	inW=sW, inH=sH, ZMin=sZ, inX=sX, inY=sY, font_factor=sFF;	}
182 
183 	/// Set size of frame in pixels. Normally this function is called internaly.
184 	virtual void SetSize(int w,int h,bool clf=true);
185 	/// Get ratio (mreal width)/(mreal height).
186 	mreal GetRatio() const MGL_FUNC_PURE;
187 	/// Get bitmap data prepared for saving to file
188 	virtual unsigned char **GetRGBLines(long &w, long &h, unsigned char *&f, bool alpha=false);
189 	/// Get RGB bitmap of current state image.
190 	virtual const unsigned char *GetBits();
191 	/// Get RGBA bitmap of background image.
GetBackground()192 	const unsigned char *GetBackground()	{	return GB;	};
193 	/// Get RGBA bitmap of current state image.
GetRGBA()194 	const unsigned char *GetRGBA()	{	Finish();	return G4;	}
195 	/// Get width of the image
GetWidth()196 	int GetWidth() const	{	return Width;	}
197 	/// Get height of the image
GetHeight()198 	int GetHeight() const	{	return Height;	}
199 	/// Combine plots from 2 canvases. Result will be saved into this.
200 	void Combine(const mglCanvas *gr);
201 	/// Set boundary box for export graphics into 2D file formats
202 	void SetBBox(int x1=0, int y1=0, int x2=-1, int y2=-1)
203 	{	BBoxX1=x1;	BBoxY1=y1;	BBoxX2=x2;	BBoxY2=y2;	}
204 
205 	/// Rasterize current plot and set it as background image
206 	void Rasterize();
207 	/// Load image for background from file (basic variant)
208 	void LoadBackground(const char *fname, double alpha=1);
209 	/// Load image for background from file.
210 	/** Parameter 'how' can be:
211 	 *   'a' for filling current subplot only;
212 	 *   's' for spline-based resizing;
213 	 *   'f' for fixing aspect ratio at resizing;
214 	 *   'c' for centering image;
215 	 *   't' for tessellate image. */
216 	void LoadBackground(const char *fname, const char *how, double alpha=1);
217 	/// Fill background image by specified color
218 	void FillBackground(const mglColor &cc);
219 
GetDelay()220 	inline mreal GetDelay() const	{	return Delay;	}
SetDelay(mreal d)221 	inline void SetDelay(mreal d)	{	Delay=d;	}
222 
223 	/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
224 	mglPoint CalcXYZ(int xs, int ys, bool real=false) const MGL_FUNC_PURE;
225 	/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
226 	void CalcScr(mglPoint p, int *xs, int *ys) const;
227 	mglPoint CalcScr(const mglPoint &p) const;
228 	/// Set object/subplot id
SetObjId(long id)229 	inline void SetObjId(long id)	{	ObjId = id;	}
230 	/// Get object id
GetObjId(long xs,long ys)231 	inline int GetObjId(long xs,long ys) const
232 	{	long i=xs+Width*ys;	return (i>=0 && i<Width*Height)?OI[i]:-1;	}
233 	/// Get subplot id
234 	int GetSplId(long xs,long ys) const MGL_FUNC_PURE;
235 	/// Check if there is active point or primitive (n=-1)
236 	int IsActive(int xs, int ys,int &n);
237 
238 	/// Create new frame.
239 	virtual int NewFrame();
240 	/// Finish frame drawing
241 	virtual void EndFrame();
242 	/// Get the number of created frames
GetNumFrame()243 	inline int GetNumFrame() const	{	return CurFrameId;	}
244 	/// Reset frames counter (start it from zero)
245 	virtual void ResetFrames();
246 	/// Delete primitives for i-th frame
247 	virtual void DelFrame(long i);
248 	/// Get drawing data for i-th frame.
249 	void GetFrame(long i);
250 	/// Set drawing data for i-th frame. This work as EndFrame() but don't add frame to GIF image.
251 	virtual void SetFrame(long i);
252 	/// Add drawing data from i-th frame to the current drawing
253 	void ShowFrame(long i);
254 	/// Clear list of primitives for current drawing
255 	void ClearFrame();
256 
257 	/// Start write frames to cinema using GIF format
258 	void StartGIF(const char *fname, int ms=100);
259 	/// Stop writing cinema using GIF format
260 	void CloseGIF();
261 	/// Finish plotting. Normally this function is called internaly.
262 	virtual void Finish();
263 	/// Export points and primitives in file using MGLD format
264 	bool ExportMGLD(const char *fname, const char *descr=0);
265 	/// Import points and primitives from file using MGLD format
266 	bool ImportMGLD(const char *fname, bool add=false);
267 	/// Export in JSON format suitable for later drawing by JavaScript
268 	bool WriteJSON(const char *fname, bool force_zlib=false);
269 	std::string GetJSON();
270 
271 	/// Set the transparency type
SetTranspType(int val)272 	inline void SetTranspType(int val)
273 	{	Flag=(Flag&(~3)) + (val&3);	SetAxisStl(val==2?"w-":"k-");	}
274 	/// Set the fog distance or switch it off (if d=0).
275 	virtual void Fog(mreal d, mreal dz=0.25);
276 	/// Switch on/off the specified light source.
277 	virtual void Light(int n, bool enable);
278 	/// Add a light source.
279 	virtual void AddLight(int n,mglPoint r, mglPoint d, char c='w', mreal bright=0.5, mreal ap=0);
280 	inline void AddLight(int n,mglPoint d, char c='w', mreal bright=0.5, mreal ap=0)
281 	{	AddLight(n,mglPoint(NAN),d,c,bright,ap);	}
282 
283 	/// Set ticks position and text (\n separated). Use n=0 to disable this feature.
284 	void SetTicksVal(char dir, const char *lbl, bool add=false);
285 	void SetTicksVal(char dir, HCDT v, const char *lbl, bool add=false);
286 	void SetTicksVal(char dir, HCDT v, const char **lbl, bool add=false);
287 	void SetTicksVal(char dir, const wchar_t *lbl, bool add=false);
288 	void SetTicksVal(char dir, HCDT v, const wchar_t *lbl, bool add=false);
289 	void SetTicksVal(char dir, HCDT v, const wchar_t **lbl, bool add=false);
290 		/// Add manual tick at given position. Use "" to disable this feature.
291 	void AddTick(char dir, double val, const char *lbl);
292 	void AddTick(char dir, double val, const wchar_t *lbl);
293 
294 	/// Set templates for ticks
295 	void SetTickTempl(char dir, const wchar_t *t);
296 	void SetTickTempl(char dir, const char *t);
297 	/// Set time templates for ticks
298 	void SetTickTime(char dir, mreal d=0, const char *t="");
299 	/// Set the ticks parameters
300 	void SetTicks(char dir, mreal d=0, int ns=0, mreal org=NAN, const wchar_t *lbl=0);
301 	/// Auto adjust ticks
302 	void AdjustTicks(const char *dir="xyzc", bool force=false, const std::string &stl="");
303 	/// Tune ticks
304 	inline void SetTuneTicks(int tune, mreal pos=1.15)
305 	{	TuneTicks = tune;	FactorPos = pos;	}
306 	/// Set ticks styles
307 	void SetAxisStl(const char *stl="k", const char *tck=0, const char *sub=0);
308 	/// Set ticks length
309 	void SetTickLen(mreal tlen, mreal stt=1.);
310 
311 	/// Draws bounding box outside the plotting volume with color c.
312 	void Box(const char *col=0, bool ticks=true);
313 	/// Draw axises with ticks in directions determined by string parameter dir.
314 	void Axis(const char *dir="xyzt", const char *stl="", const char *opt="");
315 	/// Draw grid lines perpendicular to direction determined by string parameter dir.
316 	void Grid(const char *dir="xyzt",const char *pen="B-", const char *opt="");
317 	/// Print the label text for axis dir.
318 	void Label(char dir, const char *text, mreal pos=0, const char *opt="");
319 	void Labelw(char dir, const wchar_t *text, mreal pos=0, const char *opt="");
320 
321 	/// Draw colorbar at edge of axis
322 	void Colorbar(const char *sch=0);
323 	void Colorbar(const char *sch, mreal x, mreal y, mreal w, mreal h);
324 	/// Draw colorbar at edge of axis for manual colors
325 	void Colorbar(HCDT v, const char *sch=0);
326 	void Colorbar(HCDT v, const char *sch, mreal x, mreal y, mreal w, mreal h);
327 
328 	/// Draw legend of accumulated strings at position (x, y) by font with size
329 	inline void Legend(mreal x, mreal y, const char *font="#", const char *opt="")
330 	{	Legend(Leg,x,y,font,opt);	}
331 	/// Draw legend of accumulated strings by font with size
332 	inline void Legend(int where=0x3, const char *font="#", const char *opt="")
333 	{	Legend(Leg,(where&1)?1:0,(where&2)?1:0,font,opt);	}
334 	/// Draw legend of accumulated strings by font with size
335 	inline void Legend(const std::vector<mglText> &leg, int where=3, const char *font="#", const char *opt="")
336 	{	Legend(leg,(where&1)?1:0,(where&2)?1:0,font,opt);	}
337 	/// Draw legend strings text at position (x, y) by font with size
338 	void Legend(const std::vector<mglText> &leg, mreal x, mreal y, const char *font="#", const char *opt="");
339 	/// Number of marks in legend sample
340 	inline void SetLegendMarks(int num=1)	{	LegendMarks = num>0?num:1;	}
341 
342 	/// Draw table for values val along given direction with row labels text at given position
343 	void Table(mreal x, mreal y, HCDT val, const wchar_t *text, const char *fnt, const char *opt);
344 
345 	void StartAutoGroup (const char *);
346 	void EndGroup();
347 	/// Set extra shift for tick and axis labels
SetTickShift(mglPoint p)348 	inline void SetTickShift(mglPoint p)
349 	{	ax.sh = p.x;	ay.sh = p.y;	az.sh = p.z;	ac.sh = p.c;	}
350 	/// Get rotation angle for glyph
351 	float GetGlyphPhi(const mglPnt &q, float phi);
352 
353 	// Following arrays are open for advanced users only. It is not recommended to change them directly
354 	float *Z;			///< Height for given level in Z-direction (size 3*width*height)
355 	unsigned char *C;	///< Picture for given level in Z-direction (size 3*4*width*height)
356 	int *OI;			///< ObjId arrays (size width*height)
357 	/// Plot point p with color c
358 	void pnt_plot(long x,long y,mreal z,const unsigned char c[4], int obj_id);
359 	void pnt_fast(long x,long y,mreal z,const unsigned char c[4], int obj_id);
360 	/// preparing primitives for 2d export or bitmap drawing (0 default, 1 for 2d vector, 2 for 3d vector)
361 	void PreparePrim(int fast);
GetPntCol(long i)362 	inline uint32_t GetPntCol(long i) const	{	return pnt_col[i];	}
363 	inline uint32_t GetPrmCol(long i, bool sort=true) const	{	return GetColor(GetPrm(i, sort));	}
364 	/// Set the size of semi-transparent area around lines, marks, ...
SetPenDelta(float d)365 	inline void SetPenDelta(float d)	{	pen_delta = 1.5*fabs(d);	}
366 
367 protected:
368 	mreal Delay;		///< Delay for animation in seconds
369 	// NOTE: Z should be float for reducing space and for compatibility reasons
370 	unsigned char *G4;	///< Final picture in RGBA format. Prepared in Finish().
371 	unsigned char *G;	///< Final picture in RGB format. Prepared in Finish().
372 	unsigned char *GB;	///< Background picture in RGBA format.
373 	std::vector<mglDrawDat> DrwDat;	///< Set of ALL drawing data for each frames
374 
375 	int LegendMarks;	///< Number of marks in the Legend
376 	unsigned char BDef[4];	///< Background color
377 	mglAxis ax,ay,az,ac;///< Axis parameters
378 
379 	int TuneTicks;		///< Draw tuned ticks with extracted common component
380 	mreal FactorPos;	///< Position of axis ticks factor (0 at Min, 1 at Max, 1.1 is default)
381 	mreal TickLen;		///< Length of tiks (subticks length is sqrt(1+st_t)=1.41... times smaller)
382 	char AxisStl[32];	///< Axis line style. Default is "k"
383 	char TickStl[32];	///< Tick line style. Default is "k"
384 	char SubTStl[32];	///< Subtick line style. Default is "k"
385 	mreal st_t;			///< Subtick-to-tick ratio (ls=lt/sqrt(1+st_t)). Default is 1.
386 
387 	int CurFrameId;		///< Number of automaticle created frames
388 	int Width;			///< Width of the image
389 	int Height;			///< Height of the image
390 	int Depth;			///< Depth of the image
391 	mreal inW, inH;		///< Width and height of last InPlot
392 	mreal inX, inY;		///< Coordinates of last InPlot
393 	mglLight light[10];	///< Light sources
394 	mreal FogDist;		///< Inverse fog distance (fog ~ exp(-FogDist*Z))
395 	mreal FogDz;		///< Relative shift of fog
396 
GetAxis(unsigned ch)397 	inline mglAxis &GetAxis(unsigned ch)
398 	{	mglAxis *aa[3]={&ax,&ay,&az};	ch-='x';	return ch<3?*(aa[ch]):ac;	}
GetFormula(unsigned ch)399 	inline HMEX GetFormula(unsigned ch)
400 	{	HMEX aa[3]={fx,fy,fz};	ch-='x';	return ch<3?aa[ch]:fa;	}
401 	/// Auto adjust ticks
402 	void AdjustTicks(mglAxis &aa, bool ff);
403 	/// Prepare labels for ticks
404 	void LabelTicks(mglAxis &aa);
405 	/// Draw axis
406 	void DrawAxis(mglAxis &aa, int text=1, char arr=0,const char *stl="",mreal angl=NAN);
407 	/// Draw axis grid lines
408 	void DrawGrid(mglAxis &aa, bool at_tick=false);
409 	/// Update axis ranges
UpdateAxis()410 	inline void UpdateAxis()
411 	{	ax.v0=Org.x;	ay.v0=Org.y;	az.v0=Org.z;	ac.v0=Org.c;
412 		ax.v1=Min.x;	ay.v1=Min.y;	az.v1=Min.z;	ac.v1=Min.c;
413 		ax.v2=Max.x;	ay.v2=Max.y;	az.v2=Max.z;	ac.v2=Max.c;	}
414 
415 	/// Clear ZBuffer only
416 	void ClfZB(bool force=false);
417 	/// Scale coordinates and cut off some points
418 	bool ScalePoint(const mglMatrix *M, mglPoint &p, mglPoint &n, bool use_nan=true) const;
419 	void LightScale(const mglMatrix *M);	///< Additionally scale positions of light sources
420 	void LightScale(const mglMatrix *M, mglLight &l);	///< Additionally scale positions of light
421 	/// Push drawing data (for frames only). NOTE: can be VERY large
422 	long PushDrwDat();
423 	/// Retur color for primitive depending lighting
424 	uint32_t GetColor(const mglPrim &p) const MGL_FUNC_PURE;
425 
426 	mreal GetOrgX(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.x (parse NAN value)
427 	mreal GetOrgY(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.y (parse NAN value)
428 	mreal GetOrgZ(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.z (parse NAN value)
429 
430 	void mark_plot(long p, char type, mreal size=1);
431 	void arrow_plot(long p1, long p2, char st);
432 	void line_plot(long p1, long p2);
433 	void trig_plot(long p1, long p2, long p3);
434 	void quad_plot(long p1, long p2, long p3, long p4);
435 	void Glyph(mreal x, mreal y, mreal f, int style, long icode, mreal col);
436 	void smbl_plot(long p1, char id, double size);
437 	mreal text_plot(long p,const wchar_t *text,const char *fnt,mreal size=-1,mreal sh=0,mreal  col=-('k'), bool rot=true);
438 
439 	void add_prim(mglPrim &a);	///< add primitive to list
440 	void arrow_draw(const mglPnt &p1, const mglPnt &p2, char st, mreal size, const mglDrawReg *d);
441 	virtual void mark_draw(const mglPnt &p, char type, mreal size, mglDrawReg *d);
442 	virtual void line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
443 	virtual void trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d);
444 	virtual void quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d);
445 	virtual void pnt_draw(const mglPnt &p, const mglDrawReg *d);
446 	void arrow_draw(long n1, long n2, char st, float ll);
447 	void arrow_plot_3d(long n1, long n2, char st, float ll);
448 	void glyph_draw(const mglPrim &P, mglDrawReg *d);
449 	void glyph_draw_new(const mglPrim &P, mglDrawReg *d);
450 	bool IsSame(const mglPrim &pr,mreal wp,mglColor cp,int st);
451 
452 	// check if visible
453 	bool trig_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3) const;
454 	bool quad_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4) const;
455 
456 	// functions for glyph drawing
457 	virtual void glyph_fill(mreal phi, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
458 	void glyph_wire(mreal phi, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
459 	void glyph_line(mreal phi, const mglPnt &p, mreal f, bool solid, const mglDrawReg *d);
460 
461 	// restore normalized coordinates from screen ones
462 	mglPoint RestorePnt(mglPoint ps, bool norm=false) const MGL_FUNC_PURE;
463 
464 	// functions for multi-threading
465 	void pxl_pntcol(long id, long n, const void *);
466 	void pxl_combine(long id, long n, const void *);
467 	void pxl_memcpy(long id, long n, const void *);
468 	void pxl_backgr(long id, long n, const void *);
469 	void pxl_primdr(long id, long n, const void *);
470 	void pxl_dotsdr(long id, long n, const void *);
471 	void pxl_primpx(long id, long n, const void *);
472 	void pxl_transform(long id, long n, const void *);
473 	void pxl_setz(long id, long n, const void *);
474 	void pxl_setz_adv(long id, long n, const void *);
475 	void pxl_other(long id, long n, const void *p);
476 	/// Put drawing from other mglCanvas (for multithreading, like subplots)
477 	void PutDrawReg(mglDrawReg *d, const mglCanvas *gr);
478 
479 private:
mglCanvas(const mglCanvas &)480     mglCanvas(const mglCanvas &){}	// copying is not allowed
481 	const mglCanvas &operator=(const mglCanvas &t){return t;}	// copying is not allowed
482 
483 	mglMatrix sB;	// parameters of saved inplot
484 	mreal sW, sH, sZ, sX, sY, sFF;
485 
486 	uint32_t *pnt_col;
487 //	mreal _tetx,_tety,_tetz;		// extra angles
488 	std::vector<mglMatrix> stack;	///< stack for transformation matrices
489 	GifFileType *gif;
490 	mreal fscl,ftet;	///< last scale and rotation for glyphs
491 	long forg;			///< original point (for directions)
492 	size_t grp_counter;	///< Counter for StartGroup(); EndGroup();
493 	mglMatrix Bt;		///< temporary matrix for text
494 	float pen_delta;	///< delta pen width (dpw) -- the size of semi-transparent region for lines, marks, ...
495 
496 	/// Draw generic colorbar
497 	void colorbar(HCDT v, const mreal *s, int where, mreal x, mreal y, mreal w, mreal h, bool text);
498 	/// Draw labels for ticks
499 	void DrawLabels(mglAxis &aa, bool inv=false, const mglMatrix *M=0);
500 	/// Get label style
501 	char GetLabelPos(mreal c, long kk, mglAxis &aa);
502 	/// Draw tick
503 	void tick_draw(mglPoint o, mglPoint d1, mglPoint d2, int f);
504 	mreal FindOptOrg(char dir, int ind) const MGL_FUNC_PURE;
505 	/// Transform mreal color and alpha to bits format
506 	void col2int(const mglPnt &p, unsigned char *r, int obj_id) const;
507 	/// Combine colors in 2 plane.
508 	void combine(unsigned char *c1, const unsigned char *c2) const;
509 	/// Fast drawing of line between 2 points
510 	void fast_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
511 
512 	/// Additionally scale points p for positioning in image
513 	void PostScale(const mglMatrix *M, mglPoint &p) const;
514 	/// Scale points p for projection to the face number nface in image
515 	long ProjScale(int nface, long p, bool text=false);
516 	/// Set coordinate and add the point, return its id
517 	long setPp(mglPnt &q, const mglPoint &p);
518 
519 	// fill pixel for given primitive
520 	void mark_pix(long i,long j,const mglPnt &p, char type, mreal size, mglDrawReg *d);
521 	void arrow_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, char st, mreal size, const mglDrawReg *d);
522 	void line_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
523 	void trig_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d);
524 	void quad_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d);
525 	void glyph_pix(long i,long j,const mglPrim &P, mglDrawReg *d);
526 	void pnt_pix(long i,long j,const mglPnt &p, const mglDrawReg *d);
527 	void glyph_fpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
528 	void glyph_wpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
529 	void glyph_lpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, bool solid, const mglDrawReg *d);
530 };
531 //-----------------------------------------------------------------------------
532 struct mglThreadG
533 {
534 	mglCanvas *gr;		// grapher
535 	void (mglCanvas::*f)(long i, long n, const void *);
536 	unsigned id;		// thread id
537 	long n;	// total number of iteration
538 	const void *p;		// external parameter
539 };
540 /// Start several thread for the task
541 void mglStartThread(void (mglCanvas::*func)(long i, long n), mglCanvas *gr, long n);
542 //-----------------------------------------------------------------------------
get_persp(float pf,float z,float Depth)543 inline mreal get_persp(float pf, float z, float Depth)
544 //{	return (1-pf)/(1-pf*z/Depth);	}
545 {	return (1-pf/1.37)/(1-pf*z/Depth);	}
get_pfact(float pf,float Depth)546 inline mreal get_pfact(float pf, float Depth)
547 //{	return pf/(1-pf)/Depth;	}
548 {	return pf/(1-pf/1.37)/Depth;	}
549 //-----------------------------------------------------------------------------
550 #endif
551