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