1 /***************************************************************************
2  * crust.cpp 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 #include <float.h>
21 #include <list>
22 #include <limits>
23 #include "mgl2/other.h"
24 #include "mgl2/data.h"
25 #include "mgl2/thread.h"
26 #include "mgl2/base.h"
27 //-----------------------------------------------------------------------------
28 //
29 //	TriPlot series
30 //
31 //-----------------------------------------------------------------------------
mgl_triplot_xyzc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)32 void MGL_EXPORT mgl_triplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
33 {
34 	long n = x->GetNN(), m = nums->GetNy();
35 	if(mgl_check_trig(gr,nums,x,y,z,a,"TriPlot"))	return;
36 
37 	long ss=gr->AddTexture(sch);
38 	gr->SaveState(opt);	gr->SetPenPal("-");
39 	static int cgid=1;	gr->StartGroup("TriPlot",cgid++);
40 
41 	bool wire = mglchr(sch,'#');
42 	long nc = a->GetNN();
43 	if(nc!=n && nc>=m)	// colors per triangle
44 	{
45 		mglPoint p1,p2,p3,q;
46 		long kq = gr->AllocPnts(m*3);
47 #pragma omp parallel for
48 		for(long i=0;i<m;i++)
49 		{
50 			if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)
51 			{
52 				long k1 = long(nums->v(0,i)+0.5);
53 				mglPoint p1(x->v(k1), y->v(k1), z->v(k1));
54 				long k2 = long(nums->v(1,i)+0.5);
55 				mglPoint p2(x->v(k2), y->v(k2), z->v(k2));
56 				long k3 = long(nums->v(2,i)+0.5);
57 				mglPoint p3(x->v(k3), y->v(k3), z->v(k3));
58 				mglPoint q(wire ? mglPoint(NAN,NAN) : (p2-p1) ^ (p3-p1));
59 				mreal cc = a->v(i);
60 				gr->AddPntQ(kq+3*i,p1,gr->GetC(ss,cc),q);
61 				gr->AddPntQ(kq+3*i+1,p2,gr->GetC(ss,cc),q);
62 				gr->AddPntQ(kq+3*i+2,p3,gr->GetC(ss,cc),q);
63 			}
64 			else
65 			{	gr->SetPntOff(kq+3*i);	gr->SetPntOff(kq+3*i+1);	gr->SetPntOff(kq+3*i+2);	}
66 		}
67 		if(wire)	for(long i=0;i<m;i++)
68 		{
69 			gr->line_plot(kq+3*i,kq+3*i+1);
70 			gr->line_plot(kq+3*i+1,kq+3*i+2);
71 			gr->line_plot(kq+3*i+2,kq+3*i);
72 		}
73 		else	for(long i=0;i<m;i++)	gr->trig_plot(kq+3*i,kq+3*i+1,kq+3*i+2);
74 	}
75 	else if(nc>=n)		// colors per point
76 	{
77 		mglPoint *pp = new mglPoint[n];
78 		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)	// add averaged normales
79 		{
80 			long k1 = long(nums->v(0,i)+0.5);
81 			long k2 = long(nums->v(1,i)+0.5);
82 			long k3 = long(nums->v(2,i)+0.5);
83 			if(!wire)
84 			{
85 				mglPoint q(mglPoint(x->v(k2)-x->v(k1), y->v(k2)-y->v(k1), z->v(k2)-z->v(k1)) ^
86 					mglPoint(x->v(k3)-x->v(k1), y->v(k3)-y->v(k1), z->v(k3)-z->v(k1)));
87 				q.Normalize();
88 				// try be sure that in the same direction ...
89 				if(q.z<0)	q *= -1;
90 				pp[k1] += q;	pp[k2] += q;	pp[k3] += q;
91 			}
92 			else	pp[k1]=pp[k2]=pp[k3]=mglPoint(NAN,NAN);
93 		}
94 		long kq = gr->AllocPnts(n);
95 #pragma omp parallel for
96 		for(long i=0;i<n;i++)	// add points
97 			gr->AddPntQ(kq+i, mglPoint(x->v(i), y->v(i), z->v(i)), gr->GetC(ss,a->v(i)), pp[i]);
98 		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)	// draw triangles
99 		{
100 			long k1 = long(nums->v(0,i)+0.5);
101 			long k2 = long(nums->v(1,i)+0.5);
102 			long k3 = long(nums->v(2,i)+0.5);
103 			if(wire)
104 			{
105 				gr->line_plot(kq+k1,kq+k2);	gr->line_plot(kq+k1,kq+k3);
106 				gr->line_plot(kq+k3,kq+k2);
107 			}
108 			else	gr->trig_plot(kq+k1,kq+k2,kq+k3);
109 		}
110 		delete []pp;
111 	}
112 	gr->EndGroup();
113 }
114 //-----------------------------------------------------------------------------
mgl_triplot_xyz(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)115 void MGL_EXPORT mgl_triplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
116 {	mgl_triplot_xyzc(gr,nums,x,y,z,z,sch,opt);	}
117 //-----------------------------------------------------------------------------
mgl_triplot_xy(HMGL gr,HCDT nums,HCDT x,HCDT y,const char * sch,const char * opt)118 void MGL_EXPORT mgl_triplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt)
119 {
120 	gr->SaveState(opt);
121 	mglData z(x->GetNN());
122 	mreal zm = gr->AdjustZMin();	z.Fill(zm,zm);
123 	mgl_triplot_xyzc(gr,nums,x,y,&z,&z,sch,0);
124 }
125 //-----------------------------------------------------------------------------
mgl_triplot_xyzc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)126 void MGL_EXPORT mgl_triplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
127 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
128 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
129 	mgl_triplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
130 	delete []o;	delete []s;	}
131 //-----------------------------------------------------------------------------
mgl_triplot_xyz_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)132 void MGL_EXPORT mgl_triplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
133 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
134 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
135 	mgl_triplot_xyz(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
136 	delete []o;	delete []s;	}
137 //-----------------------------------------------------------------------------
mgl_triplot_xy_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,const char * sch,const char * opt,int l,int lo)138 void MGL_EXPORT mgl_triplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int l,int lo)
139 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
140 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
141 	mgl_triplot_xy(_GR_, _DA_(nums), _DA_(x), _DA_(y), s, o);	delete []o;	delete []s;	}
142 //-----------------------------------------------------------------------------
143 //
144 //	QuadPlot series
145 //
146 //-----------------------------------------------------------------------------
mgl_quadplot_xyzc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)147 void MGL_EXPORT mgl_quadplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
148 {
149 	long n = x->GetNN(), m = nums->GetNy();
150 	if(mgl_check_trig(gr,nums,x,y,z,a,"QuadPlot",4))	return;
151 
152 	long ss=gr->AddTexture(sch);
153 	gr->SaveState(opt);	gr->SetPenPal("-");
154 	static int cgid=1;	gr->StartGroup("QuadPlot",cgid++);
155 	mglPoint p1,p2,p3,p4;
156 
157 	long nc = a->GetNN();
158 	bool wire = mglchr(sch,'#');
159 	if(nc!=n && nc>=m)	// colors per triangle
160 	{
161 		long kq = gr->AllocPnts(m*4);
162 #pragma omp parallel for
163 		for(long i=0;i<m;i++)
164 		{
165 			if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
166 			{
167 				long k1 = long(nums->v(0,i)+0.5);
168 				p1.Set(x->v(k1), y->v(k1), z->v(k1));
169 				long k2 = long(nums->v(1,i)+0.5);
170 				p2.Set(x->v(k2), y->v(k2), z->v(k2));
171 				long k3 = long(nums->v(2,i)+0.5);
172 				p3.Set(x->v(k3), y->v(k3), z->v(k3));
173 				long k4 = long(nums->v(3,i)+0.5);
174 				p4.Set(x->v(k4), y->v(k4), z->v(k4));
175 				mglPoint q = wire ? mglPoint(NAN,NAN):(p2-p1) ^ (p3-p1);
176 				mreal cc = a->v(i);
177 				gr->AddPntQ(kq+4*i,p1,gr->GetC(ss,cc),q);
178 				gr->AddPntQ(kq+4*i+1,p2,gr->GetC(ss,cc),q);
179 				gr->AddPntQ(kq+4*i+2,p3,gr->GetC(ss,cc),q);
180 				gr->AddPntQ(kq+4*i+3,p4,gr->GetC(ss,cc),q);
181 			}
182 			else
183 			{	gr->SetPntOff(kq+4*i);		gr->SetPntOff(kq+4*i+1);
184 				gr->SetPntOff(kq+4*i+1);	gr->SetPntOff(kq+4*i+3);	}
185 		}
186 		if(wire)	for(long i=0;i<m;i++)
187 		{
188 			gr->line_plot(kq+3*i,kq+3*i+1);
189 			gr->line_plot(kq+3*i+1,kq+3*i+2);
190 			gr->line_plot(kq+3*i+2,kq+3*i);
191 		}
192 		else	for(long i=0;i<m;i++)
193 			gr->quad_plot(kq+4*i,kq+4*i+1,kq+4*i+2,kq+4*i+3);
194 
195 	}
196 	else if(nc>=n)		// colors per point
197 	{
198 		long *kk = new long[n];
199 		mglPoint *pp = new mglPoint[n];
200 		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
201 		{	// add averaged normales
202 			long k1 = long(nums->v(0,i)+0.5);
203 			p1.Set(x->v(k1), y->v(k1), z->v(k1));
204 			long k2 = long(nums->v(1,i)+0.5);
205 			p2.Set(x->v(k2), y->v(k2), z->v(k2));
206 			long k3 = long(nums->v(2,i)+0.5);
207 			p3.Set(x->v(k3), y->v(k3), z->v(k3));
208 			long k4 = long(nums->v(3,i)+0.5);
209 			p4.Set(x->v(k4), y->v(k4), z->v(k4));
210 
211 			if(wire)	pp[k1]=pp[k2]=pp[k3]=pp[k4]=mglPoint(NAN,NAN);
212 			else
213 			{
214 				mglPoint q1 = (p2-p1) ^ (p3-p1);	if(q1.z<0) q1*=-1;
215 				mglPoint q2 = (p2-p4) ^ (p3-p4);	if(q2.z<0) q2*=-1;
216 				mglPoint q3 = (p1-p2) ^ (p4-p2);	if(q3.z<0) q3*=-1;
217 				mglPoint q4 = (p1-p4) ^ (p4-p3);	if(q4.z<0) q4*=-1;
218 				pp[k1] += q1;	pp[k2] += q2;	pp[k3] += q3;	pp[k4] += q4;
219 			}
220 		}
221 		long kq = gr->AllocPnts(n);
222 #pragma omp parallel for
223 		for(long i=0;i<n;i++)	// add points
224 			gr->AddPntQ(kq+i, mglPoint(x->v(i), y->v(i), z->v(i)),gr->GetC(ss,a->v(i)), pp[i]);
225 		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
226 		{	// draw quads
227 			long k1 = long(nums->v(0,i)+0.5);
228 			long k2 = long(nums->v(1,i)+0.5);
229 			long k3 = long(nums->v(2,i)+0.5);
230 			long k4 = long(nums->v(3,i)+0.5);
231 			if(wire)
232 			{
233 				gr->line_plot(kq+k1,kq+k2);	gr->line_plot(kq+k1,kq+k3);
234 				gr->line_plot(kq+k4,kq+k2);	gr->line_plot(kq+k4,kq+k3);
235 			}
236 			else	gr->quad_plot(kq+k1,kq+k2,kq+k3,kq+k4);
237 		}
238 		delete []kk;	delete []pp;
239 	}
240 	gr->EndGroup();
241 }
242 //-----------------------------------------------------------------------------
mgl_quadplot_xyz(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)243 void MGL_EXPORT mgl_quadplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
244 {	mgl_quadplot_xyzc(gr,nums,x,y,z,z,sch,opt);	}
245 //-----------------------------------------------------------------------------
mgl_quadplot_xy(HMGL gr,HCDT nums,HCDT x,HCDT y,const char * sch,const char * opt)246 void MGL_EXPORT mgl_quadplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt)
247 {
248 	gr->SaveState(opt);
249 	mglData z(x->GetNN());	z.Fill(gr->Min.z,gr->Min.z);
250 	mgl_quadplot_xyzc(gr,nums,x,y,&z,&z,sch,0);
251 }
252 //-----------------------------------------------------------------------------
mgl_quadplot_xyzc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)253 void MGL_EXPORT mgl_quadplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
254 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
255 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
256 	mgl_quadplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
257 	delete []o;	delete []s;}
258 //-----------------------------------------------------------------------------
mgl_quadplot_xyz_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)259 void MGL_EXPORT mgl_quadplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
260 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
261 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
262 	mgl_quadplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(z), s, o);
263 	delete []o;	delete []s;}
264 //-----------------------------------------------------------------------------
mgl_quadplot_xy_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,const char * sch,const char * opt,int l,int lo)265 void MGL_EXPORT mgl_quadplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int l,int lo)
266 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
267 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
268 	mgl_quadplot_xy(_GR_, _DA_(nums), _DA_(x), _DA_(y), s, o);	delete []o;	delete []s;	}
269 //-----------------------------------------------------------------------------
270 //
271 //	TriCont series
272 //
273 //-----------------------------------------------------------------------------
274 #include "cont.hpp"
275 //-----------------------------------------------------------------------------
mgl_tri_lines(mreal val,HCDT nums,HCDT a,HCDT x,HCDT y,HCDT z)276 std::vector<mglSegment> MGL_NO_EXPORT mgl_tri_lines(mreal val, HCDT nums, HCDT a, HCDT x, HCDT y, HCDT z)
277 {
278 	long n = x->GetNN(), m = nums->GetNy();
279 	std::vector<mglSegment> lines;
280 	for(long i=0;i<m;i++)
281 	{
282 		long k1 = long(nums->v(0,i)+0.5), k2 = long(nums->v(1,i)+0.5), k3 = long(nums->v(2,i)+0.5);
283 		if(k1<0 || k1>=n || k2<0 || k2>=n || k3<0 || k3>=n)	continue;
284 		mreal v1 = a->v(k1), v2 = a->v(k2), v3 = a->v(k3);
285 		mreal d1 = mgl_d(val,v1,v2), d2 = mgl_d(val,v1,v3), d3 = mgl_d(val,v2,v3);
286 		mglSegment line;
287 		if(d1>=0 && d1<=1 && d2>=0 && d2<=1)
288 		{
289 			line.p1.Set(x->v(k1)*(1-d1)+x->v(k2)*d1, y->v(k1)*(1-d1)+y->v(k2)*d1, z->v(k1)*(1-d1)+z->v(k2)*d1);
290 			line.p2.Set(x->v(k1)*(1-d2)+x->v(k3)*d2, y->v(k1)*(1-d2)+y->v(k3)*d2, z->v(k1)*(1-d2)+z->v(k3)*d2);
291 		}
292 		else if(d1>=0 && d1<=1 && d3>=0 && d3<=1)
293 		{
294 			line.p1.Set(x->v(k1)*(1-d1)+x->v(k2)*d1, y->v(k1)*(1-d1)+y->v(k2)*d1, z->v(k1)*(1-d1)+z->v(k2)*d1);
295 			line.p2.Set(x->v(k2)*(1-d3)+x->v(k3)*d3, y->v(k2)*(1-d3)+y->v(k3)*d3, z->v(k2)*(1-d3)+z->v(k3)*d3);
296 		}
297 		else if(d3>=0 && d3<=1 && d2>=0 && d2<=1)
298 		{
299 			line.p1.Set(x->v(k1)*(1-d2)+x->v(k3)*d2, y->v(k1)*(1-d2)+y->v(k3)*d2, z->v(k1)*(1-d2)+z->v(k3)*d2);
300 			line.p2.Set(x->v(k2)*(1-d3)+x->v(k3)*d3, y->v(k2)*(1-d3)+y->v(k3)*d3, z->v(k2)*(1-d3)+z->v(k3)*d3);
301 		}
302 		if(line.p1!=line.p2)	lines.push_back(line);
303 	}
304 	return lines;
305 }
306 //-----------------------------------------------------------------------------
mgl_tricont_xyzcv(HMGL gr,HCDT v,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)307 void MGL_EXPORT mgl_tricont_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
308 {
309 	mglDataV zz(x->GetNN());
310 	if(!z)	z = &zz;
311 	if(mgl_check_trig(gr,nums,x,y,z,a,"TriCont"))	return;
312 
313 	gr->SaveState(opt);
314 	static int cgid=1;	gr->StartGroup("TriCont",cgid++);
315 	int text=0;
316 	if(mglchr(sch,'t'))	text=1;
317 	if(mglchr(sch,'T'))	text=2;
318 	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
319 	long s=gr->AddTexture(sch);
320 	gr->SetPenPal(sch);
321 
322 	for(long k=0;k<v->GetNx();k++)
323 	{
324 		mreal v0 = v->v(k);		zz.Fill(fixed ? gr->Min.z : v0);
325 		mgl_draw_curvs(gr,v0,gr->GetC(s,v0),text,mgl_get_curvs(gr,mgl_tri_lines(v0,nums,a,x,y,fixed?&zz:z)));
326 	}
327 }
328 //-----------------------------------------------------------------------------
mgl_tricont_xyzc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)329 void MGL_EXPORT mgl_tricont_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
330 {
331 	mreal r = gr->SaveState(opt);
332 	long n = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
333 	mglData v(n);
334 	for(long i=0;i<n;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(n+1);
335 	mgl_tricont_xyzcv(gr,&v,nums,x,y,z,a,sch,0);
336 }
337 //-----------------------------------------------------------------------------
mgl_tricont_xyc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)338 void MGL_EXPORT mgl_tricont_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
339 {	mgl_tricont_xyzc(gr,nums,x,y,0,z,sch,opt);	}
340 //-----------------------------------------------------------------------------
mgl_tricont_xycv(HMGL gr,HCDT v,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)341 void MGL_EXPORT mgl_tricont_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
342 {	mgl_tricont_xyzcv(gr,v,nums,x,y,0,z,sch,opt);	}
343 //-----------------------------------------------------------------------------
mgl_tricont_xyzcv_(uintptr_t * gr,uintptr_t * v,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)344 void MGL_EXPORT mgl_tricont_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
345 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
346 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
347 	mgl_tricont_xyzcv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
348 	delete []o;	delete []s;	}
349 //-----------------------------------------------------------------------------
mgl_tricont_xycv_(uintptr_t * gr,uintptr_t * v,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)350 void MGL_EXPORT mgl_tricont_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
351 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
352 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
353 	mgl_tricont_xycv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
354 	delete []o;	delete []s;	}
355 //-----------------------------------------------------------------------------
mgl_tricont_xyzc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)356 void MGL_EXPORT mgl_tricont_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt, int l,int lo)
357 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
358 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
359 	mgl_tricont_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
360 	delete []o;	delete []s;	}
361 //-----------------------------------------------------------------------------
mgl_tricont_xyc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)362 void MGL_EXPORT mgl_tricont_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt, int l,int lo)
363 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
364 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
365 	mgl_tricont_xyc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
366 	delete []o;	delete []s;	}
367 //-----------------------------------------------------------------------------
368 //
369 //	TriContV series
370 //
371 //-----------------------------------------------------------------------------
mgl_tricontv_xyzcv(HMGL gr,HCDT v,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)372 void MGL_EXPORT mgl_tricontv_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
373 {
374 	mglDataV zz(x->GetNN());
375 	if(!z)	z = &zz;
376 	if(mgl_check_trig(gr,nums,x,y,z,a,"TriContV"))	return;
377 
378 	gr->SaveState(opt);
379 	static int cgid=1;	gr->StartGroup("TriContV",cgid++);
380 	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
381 	long s=gr->AddTexture(sch);
382 	gr->SetPenPal(sch);
383 
384 	for(long k=0;k<v->GetNx();k++)
385 	{
386 		mreal v0 = v->v(k);		zz.Fill(fixed ? gr->Min.z : v0);
387 		mreal dv = (gr->Max.c-gr->Min.c)/8, c = gr->GetC(s,v0);
388 		if(k>0)	dv = v->v(k-1)-v->v(k);
389 		else if(k<v->GetNx()-1)	dv = v->v(k)-v->v(k+1);
390 		if(fixed)	dv=-dv;
391 
392 		const std::vector<mglSegment> curvs = mgl_get_curvs(gr,mgl_tri_lines(v0,nums,a,x,y,fixed?&zz:z));
393 		for(size_t i=0;i<curvs.size();i++)
394 		{
395 			const std::list<mglPoint> &pp=curvs[i].pp;
396 			long f2=-1,g2=-1;
397 			for(std::list<mglPoint>::const_iterator it=pp.begin(); it != pp.end(); ++it)
398 			{
399 				mglPoint p=*it,q(p.y,-p.x);
400 				long f1 = f2;	f2 = gr->AddPnt(p,c,q);	p.z+=dv;
401 				long g1 = g2;	g2 = gr->AddPnt(p,c,q);
402 				gr->quad_plot(f1,g1,f2,g2);
403 			}
404 		}
405 	}
406 }
407 //-----------------------------------------------------------------------------
mgl_tricontv_xyzc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)408 void MGL_EXPORT mgl_tricontv_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
409 {
410 	mreal r = gr->SaveState(opt);
411 	long n = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
412 	mglData v(n);
413 	for(long i=0;i<n;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(n+1);
414 	mgl_tricontv_xyzcv(gr,&v,nums,x,y,z,a,sch,0);
415 }
416 //-----------------------------------------------------------------------------
mgl_tricontv_xyc(HMGL gr,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)417 void MGL_EXPORT mgl_tricontv_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
418 {	mgl_tricontv_xyzc(gr,nums,x,y,0,z,sch,opt);	}
419 //-----------------------------------------------------------------------------
mgl_tricontv_xycv(HMGL gr,HCDT v,HCDT nums,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)420 void MGL_EXPORT mgl_tricontv_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
421 {	mgl_tricontv_xyzcv(gr,v,nums,x,y,0,z,sch,opt);	}
422 //-----------------------------------------------------------------------------
mgl_tricontv_xyzcv_(uintptr_t * gr,uintptr_t * v,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)423 void MGL_EXPORT mgl_tricontv_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
424 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
425 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
426 	mgl_tricontv_xyzcv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
427 	delete []o;	delete []s;	}
428 //-----------------------------------------------------------------------------
mgl_tricontv_xycv_(uintptr_t * gr,uintptr_t * v,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)429 void MGL_EXPORT mgl_tricontv_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
430 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
431 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
432 	mgl_tricontv_xycv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
433 	delete []o;	delete []s;	}
434 //-----------------------------------------------------------------------------
mgl_tricontv_xyzc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * sch,const char * opt,int l,int lo)435 void MGL_EXPORT mgl_tricontv_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt, int l,int lo)
436 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
437 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
438 	mgl_tricontv_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
439 	delete []o;	delete []s;	}
440 //-----------------------------------------------------------------------------
mgl_tricontv_xyc_(uintptr_t * gr,uintptr_t * nums,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)441 void MGL_EXPORT mgl_tricontv_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt, int l,int lo)
442 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
443 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
444 	mgl_tricontv_xyc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
445 	delete []o;	delete []s;	}
446 //-----------------------------------------------------------------------------
447 //
448 //	Dots series
449 //
450 //-----------------------------------------------------------------------------
mgl_dots_ca(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT c,HCDT a,const char * sch,const char * opt)451 void MGL_EXPORT mgl_dots_ca(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt)
452 {
453 	long n = x->GetNN(), d, k=1;
454 	if(x->GetNz()>1) 	k=3;		else if(x->GetNy()>1)	k=2;
455 
456 	if(y->GetNN()!=n || z->GetNN()!=n || c->GetNN()!=n || (a && a->GetNN()!=n))
457 	{	gr->SetWarn(mglWarnDim,"Dots");	return;	}
458 	gr->SaveState(opt);
459 
460 	d = gr->MeshNum>0 ? mgl_ipow(gr->MeshNum+1,k) : n;
461 	d = n>d ? n/d:1;
462 
463 	static int cgid=1;	gr->StartGroup("Dots",cgid++);
464 	char mk=gr->SetPenPal(sch);
465 	long ss=gr->AddTexture(sch);
466 	if(mk==0)	mk='.';
467 	gr->Reserve(n);
468 
469 	long kq = gr->AllocPnts(n);
470 #pragma omp parallel for
471 	for(long i=0;i<n;i+=d)
472 	{
473 		mglPoint p(x->vthr(i),y->vthr(i),z->vthr(i));
474 		gr->AddPntQ(kq+i,p,gr->GetC(ss,c->vthr(i)),mglPoint(NAN),a?gr->GetA(a->vthr(i)):-1);
475 	}
476 	for(long i=0;i<n;i+=d)	gr->mark_plot(kq+i, mk);
477 	gr->EndGroup();
478 }
479 //-----------------------------------------------------------------------------
mgl_dots_a(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT a,const char * sch,const char * opt)480 void MGL_EXPORT mgl_dots_a(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
481 {	mgl_dots_ca(gr, x, y, z, z, a, sch, opt);	}
482 //-----------------------------------------------------------------------------
mgl_dots(HMGL gr,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)483 void MGL_EXPORT mgl_dots(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
484 {	mgl_dots_ca(gr, x, y, z, z, NULL, sch, opt);	}
485 //-----------------------------------------------------------------------------
mgl_dots_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)486 void MGL_EXPORT mgl_dots_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
487 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
488 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
489 	mgl_dots(_GR_, _DA_(x),_DA_(y),_DA_(z),s, o);	delete []o;	delete []s;	}
490 //-----------------------------------------------------------------------------
mgl_dots_a_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * a,const char * sch,const char * opt,int l,int lo)491 void MGL_EXPORT mgl_dots_a_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
492 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
493 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
494 	mgl_dots_a(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(a),s, o);	delete []o;	delete []s;	}
495 //-----------------------------------------------------------------------------
mgl_dots_ca_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,uintptr_t * a,const char * sch,const char * opt,int l,int lo)496 void MGL_EXPORT mgl_dots_ca_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
497 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
498 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
499 	mgl_dots_ca(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(c),_DA_(a),s, o);	delete []o;	delete []s;	}
500 //-----------------------------------------------------------------------------
501 //
502 //	mglTriangulation
503 //
504 //-----------------------------------------------------------------------------
505 long MGL_NO_EXPORT mgl_crust(long n,mglPoint *pp,long **nn,mreal ff);
mgl_triangulation_3d(HCDT x,HCDT y,HCDT z)506 HMDT MGL_EXPORT mgl_triangulation_3d(HCDT x, HCDT y, HCDT z)
507 {
508 	mglData *nums=0;
509 	long n = x->GetNN(), m;
510 	if(y->GetNN()!=n || z->GetNN()!=n)	return nums;
511 	mglPoint *pp = new mglPoint[n];
512 	long *nn=0;
513 	for(long i=0;i<n;i++)	pp[i].Set(x->v(i), y->v(i), z->v(i));
514 	m = mgl_crust(n,pp,&nn,0);
515 
516 	if(m>0)
517 	{
518 		nums=new mglData(3,m);
519 		for(long i=0;i<3*m;i++)	nums->a[i]=nn[i];
520 	}
521 	delete []pp;	free(nn);	return nums;
522 }
523 //-----------------------------------------------------------------------------
524 #include "s_hull/s_hull_pro.h"
mgl_triangulation_2d(HCDT x,HCDT y)525 HMDT MGL_EXPORT mgl_triangulation_2d(HCDT x, HCDT y)
526 {
527 	mglData *nums=0;
528 	long n = x->GetNN();
529 	if(y->GetNN()!=n)	return nums;
530 	// use s-hull here
531 	std::vector<Shx> pts;
532 
533 	double x1=mglInf, x2=-mglInf, y1=mglInf, y2=-mglInf;
534 	for(long i=0;i<n;i++)
535 	{
536 		mreal xx=x->vthr(i), yy = y->vthr(i);
537 		if(xx<x1)	x1=xx;
538 		if(xx>x2)	x2=xx;
539 		if(yy<y1)	y1=yy;
540 		if(yy>y2)	y2=yy;
541 	}
542 	const double dx=x2-x1, dy=y2-y1;
543 	if(dx==0 || dy==0)	return nums;
544 	for(long i=0;i<n;i++)	// Filter NaNs and Infs
545 	{
546 		Shx pt;
547 		pt.r = (x->vthr(i)-x1)/dx;	pt.c = (y->vthr(i)-y1)/dy;
548 		if(mgl_isbad(pt.r) || mgl_isbad(pt.c))	continue;
549 		pt.id = i;    pts.push_back(pt);
550 	}
551 
552 	std::vector<Triad> triads;
553 	static const double float_eps = std::numeric_limits<float>::epsilon();
554 	Dupex grid_step(float_eps, float_eps);
555 	const size_t original_size = pts.size();
556 
557 	if(pts.size() >= 3u && 0. < grid_step.r && 0. < grid_step.c) {
558 		std::vector<long> out;
559 		de_duplicate(pts, out, grid_step);
560 
561 		if (pts.size() >= 3u && s_hull_pro(pts, triads) < 0) {
562 			// Error occured. It may be caused by degenerated dataset. Well, let's try to increment rounding grid step.
563 			// Why 4? Why not. There are no particular reasons for this.
564 			grid_step.r *= 4.;
565 			grid_step.c *= 4.;
566 
567 			out.clear();
568 			triads.clear();
569 
570 			de_duplicate(pts, out, grid_step);
571 
572 			if (pts.size() >= 3u && s_hull_pro(pts, triads) < 0) {
573 				// Last try. Let's assume uniform points distribution and use range / sqrt(pts.size()) * 2 as epsilon.
574 				// It removes a 3/4 of points in optimal case but in the worst case it merges all points to the one.
575 				const double density = 1. + floor(0.5 + std::sqrt(static_cast<double>(pts.size())));
576 				grid_step.r = grid_step.c = 2/density;
577 
578 				out.clear();
579 				de_duplicate(pts, out, grid_step);
580 
581 				triads.clear();
582 				s_hull_pro(pts, triads);
583 			}
584 		}
585 	}
586 
587 	if (triads.empty()) {
588 		mgl_set_global_warn(_("Cannot triangulate this set!"));
589 	} else if(original_size > pts.size()) {
590 		mgl_set_global_warn(_("There are duplicated or indistinguishably adjacent points for triangulation."));
591 	}
592 
593 	long m = triads.size();
594 	nums=new mglData(3,m);
595 	for(long i=0;i<m;i++)
596 	{
597 		nums->a[3*i]   = triads[i].a;
598 		nums->a[3*i+1] = triads[i].b;
599 		nums->a[3*i+2] = triads[i].c;
600 	}
601 	return nums;
602 }
603 //-----------------------------------------------------------------------------
mgl_triangulation_3d_(uintptr_t * x,uintptr_t * y,uintptr_t * z)604 uintptr_t MGL_EXPORT mgl_triangulation_3d_(uintptr_t *x, uintptr_t *y, uintptr_t *z)
605 {	return uintptr_t(mgl_triangulation_3d(_DA_(x),_DA_(y),_DA_(z)));	}
mgl_triangulation_2d_(uintptr_t * x,uintptr_t * y)606 uintptr_t MGL_EXPORT mgl_triangulation_2d_(uintptr_t *x, uintptr_t *y)
607 {	return uintptr_t(mgl_triangulation_2d(_DA_(x),_DA_(y)));	}
608 //-----------------------------------------------------------------------------
609 //
610 //	DataGrid
611 //
612 //-----------------------------------------------------------------------------
mgl_grid_t(void * par)613 static void *mgl_grid_t(void *par)
614 {
615 	mglThreadD *t=(mglThreadD *)par;
616 	long nx=t->p[0],ny=t->p[1];
617 	mreal *b=t->a;
618 	const mreal *x=t->b, *y=t->c, *d=t->d;
619 	HCDT zdat = (HCDT) t->v;
620 #if !MGL_HAVE_PTHREAD
621 #pragma omp parallel for
622 #endif
623 	for(long i0=t->id;i0<t->n;i0+=mglNumThr)	if(d[3*i0]>=0 && d[3*i0+1]>=0 && d[3*i0+2]>=0)
624 	{
625 		long k1 = long(d[3*i0]+0.5), k2 = long(d[3*i0+1]+0.5), k3 = long(d[3*i0+2]+0.5);
626 		mreal dxu,dxv,dyu,dyv;
627 		mreal z1=zdat->vthr(k1), z2=zdat->vthr(k2), z3=zdat->vthr(k3);
628 		mglPoint d1(x[k2]-x[k1],y[k2]-y[k1],z2-z1), d2(x[k3]-x[k1],y[k3]-y[k1],z3-z1), p;
629 
630 		dxu = d2.x*d1.y - d1.x*d2.y;
631 		if(fabs(dxu)<1e-5) continue; // points lies on the same line
632 		dyv =-d1.x/dxu; dxv = d1.y/dxu;
633 		dyu = d2.x/dxu; dxu =-d2.y/dxu;
634 
635 		long x1,y1,x2,y2;
636 		x1 = long(mgl_min(mgl_min(x[k1],x[k2]),x[k3])); // bounding box
637 		y1 = long(mgl_min(mgl_min(y[k1],y[k2]),y[k3]));
638 		x2 = long(mgl_max(mgl_max(x[k1],x[k2]),x[k3]));
639 		y2 = long(mgl_max(mgl_max(y[k1],y[k2]),y[k3]));
640 		x1 = x1>0 ? x1:0; x2 = x2<nx ? x2:nx-1;
641 		y1 = y1>0 ? y1:0; y2 = y2<ny ? y2:ny-1;
642 		if((x1>x2) | (y1>y2)) continue;
643 
644 		mreal x0 = x[k1], y0 = y[k1];
645 		for(long i=x1;i<=x2;i++) for(long j=y1;j<=y2;j++)
646 		{
647 			mreal xx = (i-x0), yy = (j-y0);
648 			mreal u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
649 			if((u<0) | (v<0) | (u+v>1)) continue;
650 			b[i+nx*j] = z1 + d1.z*u + d2.z*v;
651 		}
652 	}
653 	return 0;
654 }
655 //-----------------------------------------------------------------------------
mgl_data_grid_xy(HMDT d,HCDT xdat,HCDT ydat,HCDT zdat,mreal x1,mreal x2,mreal y1,mreal y2)656 void MGL_EXPORT mgl_data_grid_xy(HMDT d, HCDT xdat, HCDT ydat, HCDT zdat, mreal x1, mreal x2, mreal y1, mreal y2)
657 { // NOTE: only for mglData
658 	const mglData *x = dynamic_cast<const mglData *>(xdat);
659 	const mglData *y = dynamic_cast<const mglData *>(ydat);
660 	long n=xdat->GetNN();
661 	if((n<3) || (ydat->GetNN()!=n) || (zdat->GetNN()!=n))	return;
662 
663 	mglData *nums = mgl_triangulation_2d(xdat,ydat);
664 	if(!nums)	return;
665 	if(nums->nx<3)	{	delete nums;	return;	}
666 	long nn = nums->ny, par[3]={d->nx,d->ny,d->nz};
667 	mreal xx[4]={x1,(d->nx-1)/(x2-x1), y1,(d->ny-1)/(y2-y1)};
668 
669 	mreal *xc=new mreal[n], *yc=new mreal[n];
670 	if(x && y)
671 #pragma omp parallel for
672 		for(long i=0;i<n;i++)
673 		{	xc[i]=xx[1]*(x->a[i]-xx[0]);	yc[i]=xx[3]*(y->a[i]-xx[2]);	}
674 	else
675 #pragma omp parallel for
676 		for(long i=0;i<n;i++)
677 		{	xc[i]=xx[1]*(xdat->vthr(i)-xx[0]);	yc[i]=xx[3]*(ydat->vthr(i)-xx[2]);	}
678 	long tmp = d->nx*d->ny*d->nz;
679 #pragma omp parallel for
680 	for(long i=0;i<tmp;i++) d->a[i] = NAN;
681 
682 	mglStartThread(mgl_grid_t,0,nn,d->a,xc,yc,par,zdat,nums->a);
683 	delete nums;	delete []xc;	delete []yc;
684 }
mgl_data_grid_xy_(uintptr_t * d,uintptr_t * x,uintptr_t * y,uintptr_t * z,mreal * x1,mreal * x2,mreal * y1,mreal * y2)685 void MGL_EXPORT mgl_data_grid_xy_(uintptr_t *d, uintptr_t *x, uintptr_t *y, uintptr_t *z, mreal *x1, mreal *x2, mreal *y1, mreal *y2)
686 {	mgl_data_grid_xy(_DT_,_DA_(x),_DA_(y),_DA_(z),*x1,*x2,*y1,*y2);	}
687 //-----------------------------------------------------------------------------
mgl_data_grid(HMGL gr,HMDT d,HCDT xdat,HCDT ydat,HCDT zdat,const char * opt)688 void MGL_EXPORT mgl_data_grid(HMGL gr, HMDT d, HCDT xdat, HCDT ydat, HCDT zdat, const char *opt)
689 {
690 	gr->SaveState(opt);
691 	mgl_data_grid_xy(d,xdat,ydat,zdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y);
692 	gr->LoadState();
693 }
mgl_data_grid_(uintptr_t * gr,uintptr_t * d,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * opt,int lo)694 void MGL_EXPORT mgl_data_grid_(uintptr_t *gr, uintptr_t *d, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *opt,int lo)
695 {	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
696 	mgl_data_grid(_GR_,_DT_,_DA_(x),_DA_(y),_DA_(z),o);	delete []o;	}
697 //-----------------------------------------------------------------------------
698 //
699 //	Crust series
700 //
701 //-----------------------------------------------------------------------------
mgl_crust(HMGL gr,HCDT x,HCDT y,HCDT z,const char * sch,const char * opt)702 void MGL_EXPORT mgl_crust(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
703 {
704 	if(y->GetNN()!=x->GetNN() || z->GetNN()!=x->GetNN())
705 	{	gr->SetWarn(mglWarnDim,"Crust");	return;	}
706 	HMDT nums = mgl_triangulation_3d(x, y, z);
707 	mgl_triplot_xyzc(gr,nums,x,y,z,z,sch,opt);
708 	mgl_delete_data(nums);
709 }
710 //-----------------------------------------------------------------------------
mgl_crust_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * sch,const char * opt,int l,int lo)711 void MGL_EXPORT mgl_crust_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
712 {	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
713 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
714 	mgl_crust(_GR_, _DA_(x),_DA_(y),_DA_(z),s, o);	delete []o;	delete []s;	}
715 //-----------------------------------------------------------------------------
mgl_insert_trig(long i1,long i2,long i3,long ** n)716 long static mgl_insert_trig(long i1,long i2,long i3,long **n)
717 {
718 	static long Cur=0,Max=0;
719 	if(i1<0 || i2<0 || i3<0)	return Cur;
720 	if(*n==0)
721 	{
722 		Max = 1024;		Cur = 0;
723 		*n = (long *)malloc(Max*3*sizeof(long));
724 		memset(*n,0,Max*3*sizeof(long));
725 	}
726 	if(Cur>=Max)
727 	{
728 		Max += 1024;
729 		*n = (long *)realloc(*n,Max*3*sizeof(long));
730 		memset(*n+3*(Max-1024),0,3*1024*sizeof(long));
731 	}
732 	long *nn;
733 	if(i1>i3)	{	long k1=i1;	i1=i3;	i3=k1;	}	// simple sorting
734 	if(i1>i2)	{	long k1=i1;	i1=i2;	i2=k1;	}
735 	if(i2>i3)	{	long k1=i2;	i2=i3;	i3=k1;	}
736 	for(long i=0;i<Cur;i++)	// check if it is unique
737 	{
738 		nn = *n + 3*i;
739 		if(nn[0]==i1 && nn[1]==i2 && nn[2]==i3)	return Cur;
740 	}
741 	nn = *n + 3*Cur;
742 	nn[0]=i1;	nn[1]=i2;	nn[2]=i3;
743 	Cur++;	return Cur;
744 }
745 //-----------------------------------------------------------------------------
mgl_get_next(long k1,long n,long *,long * set,mglPoint * qq)746 long static mgl_get_next(long k1,long n,long *,long *set,mglPoint *qq)
747 {
748 	long i,j=-1;
749 	mreal r,rm=FLT_MAX;
750 	for(i=0;i<n;i++)
751 	{
752 		if(i==k1 || set[i]>0)	continue;
753 		r = mgl_anorm(qq[i]-qq[k1]);
754 		if(r<rm)	{	rm=r;	j=i;	}
755 	}
756 	return j;
757 }
758 //-----------------------------------------------------------------------------
mgl_crust(long n,mglPoint * pp,long ** nn,mreal ff)759 long MGL_NO_EXPORT mgl_crust(long n,mglPoint *pp,long **nn,mreal ff)
760 {	// TODO: update to normal algorithm
761 	mreal rs=0;
762 	if(ff<=0)	ff=2;
763 	for(long i=0;i<n;i++)
764 	{
765 		mreal rm = FLT_MAX;
766 		for(long j=0;j<n;j++)
767 		{
768 			if(i==j)	continue;
769 			mreal r = mgl_anorm(pp[i]-pp[j]);
770 			if(rm>r)	rm = r;
771 		}
772 		rs += sqrt(rm);
773 	}
774 	rs *= ff/n;	rs = rs*rs;		// "average" distance
775 	const int nnum=100;
776 	long *ind, *set;	// indexes of "close" points, flag that it was added and its number
777 	mglPoint *qq;	// normalized point coordinates
778 	ind = new long[nnum];	set = new long[nnum];	qq = new mglPoint[nnum];
779 	long k1,k2,k3,m=0;
780 	for(long i=0;i<n;i++)	// now the triangles will be found
781 	{
782 		memset(set,0,nnum*sizeof(long));
783 		long ii=0;
784 		for(long j=0;j<n;j++)	// find close vertexes
785 		{
786 			mreal r = mgl_anorm(pp[i]-pp[j]);
787 			if(r<=rs && j!=i)	{	ind[ii] = j;	ii++;	if(ii==99)	break;}
788 		}
789 		if(ii<3)	continue;	// nothing to do
790 		for(long j=0;j<ii;j++)
791 		{
792 			k1 = j;	k2 = ind[j];	k3 = i;
793 			qq[k1] = pp[k2] - pp[k3];
794 			qq[k1] /= qq[k1].norm();
795 		}
796 		k1 = 0;
797 		while((k2=mgl_get_next(k1,ii,ind,set,qq))>0)
798 		{
799 			set[k1]=1;
800 			mgl_insert_trig(i,ind[k1],ind[k2],nn);
801 			k1 = k2;
802 		}
803 		m = mgl_insert_trig(i,ind[k1],ind[0],nn);
804 	}
805 	delete []set;	delete []ind;	delete []qq;	return m;
806 }
807 //-----------------------------------------------------------------------------
808