35#include <wx/graphics.h>
47wxList ocpn_wx_spline_point_list;
49#include <wx/listimpl.cpp>
50WX_DEFINE_LIST(MySegList);
51WX_DEFINE_LIST(MySegListList);
61 double xmin, xmax, ymin, ymax;
63void CompOutCode(
double x,
double y, outcode *code,
68 *code = 1L << ((long)TOP);
69 else if (y < LINK->ymin)
70 *code = 1L << ((long)BOTTOM);
72 *code |= 1L << ((long)RIGHT);
73 else if (x < LINK->xmin)
74 *code |= 1L << ((long)LEFT);
77ClipResult cohen_sutherland_line_clip_d(
double *x0,
double *y0,
double *x1,
78 double *y1,
double xmin_,
double xmax_,
79 double ymin_,
double ymax_) {
84 ClipResult clip = Visible;
85 outcode outcode0, outcode1, outcodeOut;
87 double x = 0., y = 0.;
93 CompOutCode(*x0, *y0, &outcode0, &V);
94 CompOutCode(*x1, *y1, &outcode1, &V);
96 if (outcode0 == 0 && outcode1 == 0) {
98 }
else if ((outcode0 & outcode1) != 0) {
109 outcodeOut = outcode0;
111 outcodeOut = outcode1;
115 if (((1L << ((
long)TOP)) & outcodeOut) != 0) {
117 x = *x0 + (*x1 - *x0) * (V.ymax - *y0) / (*y1 - *y0);
119 }
else if (((1L << ((
long)BOTTOM)) & outcodeOut) != 0) {
121 x = *x0 + (*x1 - *x0) * (V.ymin - *y0) / (*y1 - *y0);
123 }
else if (((1L << ((
long)RIGHT)) & outcodeOut) != 0) {
125 y = *y0 + (*y1 - *y0) * (V.xmax - *x0) / (*x1 - *x0);
127 }
else if (((1L << ((
long)LEFT)) & outcodeOut) != 0) {
129 y = *y0 + (*y1 - *y0) * (V.xmin - *x0) / (*x1 - *x0);
134 if (outcodeOut == outcode0) {
137 CompOutCode(*x0, *y0, &outcode0, &V);
141 CompOutCode(*x1, *y1, &outcode1, &V);
148ClipResult cohen_sutherland_line_clip_i(
int *x0_,
int *y0_,
int *x1_,
int *y1_,
149 int xmin_,
int xmax_,
int ymin_,
152 double x0, y0, x1, y1;
158 cohen_sutherland_line_clip_d(&x0, &y0, &x1, &y1, (
double)xmin_,
159 (
double)xmax_, (
double)ymin_, (
double)ymax_);
167double round_msvc(
double x) {
return (floor(x + 0.5)); }
172 if (wxGetDisplaySize().x > 0) {
174 m_pixelMM = wxMax(.02, m_pixelMM);
178 value = val / coeff - offset;
186 extractIsoLine(rec_);
190 if (trace.size() == 0)
return;
196 std::list<Segment *>::iterator it;
197 for (it = trace.begin(); it != trace.end(); it++) {
200 m_seglist.Append(*it);
207 MySegList *ps = BuildContinuousSegment();
209 m_SegListList.Append(ps);
211 MySegList::compatibility_iterator node;
216 node = m_seglist.GetFirst();
218 seg = node->GetData();
220 m_seglist.Erase(node);
221 node = m_seglist.GetFirst();
223 node = node->GetNext();
226 if (0 == m_seglist.GetCount()) bdone =
true;
237 std::list<Segment *>::iterator it;
238 for (it = trace.begin(); it != trace.end(); it++) {
244 m_SegListList.DeleteContents(
true);
245 m_SegListList.Clear();
248MySegList *IsoLine::BuildContinuousSegment(
void) {
249 MySegList::compatibility_iterator node;
252 MySegList *ret_list =
new MySegList;
259 node = m_seglist.GetFirst();
260 Segment *seg0 = node->GetData();
262 segjoin2.Append(seg0);
264 Segment *tseg = seg0;
269 node = m_seglist.GetFirst();
271 seg = node->GetData();
273 if ((!seg->bUsed) && (seg->py1 == tseg->py2) &&
274 (seg->px1 == tseg->px2))
277 segjoin2.Append(seg);
280 }
else if ((!seg->bUsed) && (seg->py2 == tseg->py2) &&
281 (seg->px2 == tseg->px2))
290 segjoin2.Append(seg);
295 node = node->GetNext();
308 node = m_seglist.GetFirst();
309 seg0 = node->GetData();
311 segjoin1.Append(seg0);
317 node = m_seglist.GetFirst();
319 seg = node->GetData();
321 if ((!seg->bUsed) && (seg->py2 == tseg->py1) &&
322 (seg->px2 == tseg->px1))
325 segjoin1.Append(seg);
328 }
else if ((!seg->bUsed) && (seg->py1 == tseg->py1) &&
329 (seg->px1 == tseg->px1))
338 segjoin1.Append(seg);
343 node = node->GetNext();
356 int n1 = segjoin1.GetCount();
357 for (
int i = n1 - 1; i > 0; i--) {
358 node = segjoin1.Item(i);
359 seg = node->GetData();
360 ret_list->Append(seg);
364 int n2 = segjoin2.GetCount();
365 for (
int i = 0; i < n2; i++) {
366 node = segjoin2.Item(i);
367 seg = node->GetData();
368 ret_list->Append(seg);
379 int nsegs = trace.size();
380 if (nsegs < 1)
return;
382 GetGlobalColor(_T (
"UITX1" ), &isoLineColor);
384#if wxUSE_GRAPHICS_CONTEXT
385 wxGraphicsContext *pgc =
nullptr;
389 wxPen ppISO(isoLineColor, 2);
391#if wxUSE_GRAPHICS_CONTEXT
393 pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
394 pgc = wxGraphicsContext::Create(*pmdc);
416 wxPen ppISO(isoLineColor, 2);
417 pof->m_oDC->SetPen(ppISO);
422 std::list<Segment *>::iterator it;
427 for (it = trace.begin(); it != trace.end(); it++) {
433 double sx1 = seg->px1, sx2 = seg->px2;
436 else if (sx1 - sx2 > 180)
439 if ((sx1 + 180 < vp->
clon && sx2 + 180 > vp->
clon) ||
440 (sx1 + 180 > vp->
clon && sx2 + 180 < vp->
clon) ||
441 (sx1 - 180 < vp->
clon && sx2 - 180 > vp->
clon) ||
442 (sx1 - 180 > vp->
clon && sx2 - 180 < vp->
clon))
452#if wxUSE_GRAPHICS_CONTEXT
454 pgc->StrokeLine(ab.x, ab.y, cd.x, cd.y);
457 dc->DrawLine(ab.x, ab.y, cd.x, cd.y);
462 pof->m_oDC->DrawLine(ab.x, ab.y, cd.x, cd.y);
469#if wxUSE_GRAPHICS_CONTEXT
484 std::list<Segment *>::iterator it;
492 for (it = trace.begin(); it != trace.end(); it++, nb++) {
493 if (nb % density == 0) {
504 int w = imageLabel.GetWidth();
505 int h = imageLabel.GetHeight();
507 int label_offset = 6;
508 int xd = (ab.x + cd.x - (w + label_offset * 2)) / 2;
509 int yd = (ab.y + cd.y - h) / 2;
511 int x = xd - label_offset;
512 wxRect r(x, yd, w, h);
514 if (!prev.Intersects(r)) {
519 wxImage img(w, h, imageLabel.GetData(),
true);
520 dc->DrawBitmap(img, xd, yd,
false);
528 int density,
int first, wxString label,
529 wxColour &color,
TexFont &texfont)
532 std::list<Segment *>::iterator it;
537 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
543 for (it = trace.begin(); it != trace.end(); it++, nb++) {
544 if (nb % density == 0) {
556 texfont.GetTextExtent(label, &w, &h);
558 int label_offsetx = 6, label_offsety = 1;
559 int xd = (ab.x + cd.x - (w + label_offsetx * 2)) / 2;
560 int yd = (ab.y + cd.y - h) / 2;
561 int x = xd - label_offsetx, y = yd - label_offsety;
562 w += 2 * label_offsetx, h += 2 * label_offsety;
564 wxRect r(x, y, w, h);
566 if (!prev.Intersects(r)) {
571 pof->m_oDC->SetPen(*wxBLACK_PEN);
572 pof->m_oDC->SetBrush(color);
573 pof->m_oDC->DrawRectangle(x, y, w, h);
574 pof->m_oDC->DrawText(label, xd, yd);
579 glColor4ub(color.Red(), color.Green(), color.Blue(), color.Alpha());
584 glVertex2i(x + w, y);
585 glVertex2i(x + w, y + h);
586 glVertex2i(x, y + h);
591 glBegin(GL_LINE_LOOP);
593 glVertex2i(x + w, y);
594 glVertex2i(x + w, y + h);
595 glVertex2i(x, y + h);
598 glEnable(GL_TEXTURE_2D);
599 texfont.RenderString(label, xd, yd);
600 glDisable(GL_TEXTURE_2D);
613Segment::Segment(
int I,
int w,
int J,
char c1,
char c2,
char c3,
char c4,
615 traduitCode(I, w, J, c1, i, j);
616 traduitCode(I, w, J, c2, k, l);
617 traduitCode(I, w, J, c3, m, n);
618 traduitCode(I, w, J, c4, o, p);
620 intersectionAreteGrille(i, j, k, l, &px1, &py1, rec, pressure);
621 intersectionAreteGrille(m, n, o, p, &px2, &py2, rec, pressure);
624void Segment::intersectionAreteGrille(
int i,
int j,
int k,
int l,
double *x,
627 double xa, xb, ya, yb, pa, pb, dec;
631 rec->
getXY(i, j, &xa, &ya);
632 rec->
getXY(k, l, &xb, &yb);
636 dec = (pressure - pa) / (pb - pa);
639 if (fabs(dec) > 1) dec = 0.5;
649 dec = (pressure - pa) / (pb - pa);
652 if (fabs(dec) > 1) dec = 0.5;
653 *y = ya + (yb - ya) * dec;
656void Segment::traduitCode(
int I,
int w,
int J,
char c1,
int &i,
int &j) {
657 int Im1 = I ? I - 1 : w - 1;
685void IsoLine::extractIsoLine(
const GribRecord *rec) {
692 if (rec->GetLonMax() + rec->GetDi() - rec->GetLonMin() == 360) We++;
694 for (j = 1; j < H; j++)
696 a = rec->GetValue(0, j - 1);
697 c = rec->GetValue(0, j);
698 for (i = 1; i < We; i++, a = b, c = d) {
704 b = rec->GetValue(ni, j - 1);
705 d = rec->GetValue(ni, j);
707 if (a == GRIB_NOTDEF || b == GRIB_NOTDEF || c == GRIB_NOTDEF ||
711 if ((a < value && b < value && c < value && d < value) ||
712 (a > value && b > value && c > value && d > value))
721 if ((a <= value && b <= value && c <= value && d > value) ||
722 (a > value && b > value && c > value && d <= value))
723 trace.push_back(
new Segment(ni, W, j,
'c',
'd',
'b',
'd', rec, value));
724 else if ((a <= value && c <= value && d <= value && b > value) ||
725 (a > value && c > value && d > value && b <= value))
726 trace.push_back(
new Segment(ni, W, j,
'a',
'b',
'b',
'd', rec, value));
727 else if ((c <= value && d <= value && b <= value && a > value) ||
728 (c > value && d > value && b > value && a <= value))
729 trace.push_back(
new Segment(ni, W, j,
'a',
'b',
'a',
'c', rec, value));
730 else if ((a <= value && b <= value && d <= value && c > value) ||
731 (a > value && b > value && d > value && c <= value))
732 trace.push_back(
new Segment(ni, W, j,
'a',
'c',
'c',
'd', rec, value));
736 else if ((a <= value && b <= value && c > value && d > value) ||
737 (a > value && b > value && c <= value && d <= value))
738 trace.push_back(
new Segment(ni, W, j,
'a',
'c',
'b',
'd', rec, value));
739 else if ((a <= value && c <= value && b > value && d > value) ||
740 (a > value && c > value && b <= value && d <= value))
741 trace.push_back(
new Segment(ni, W, j,
'a',
'b',
'c',
'd', rec, value));
745 else if (a <= value && d <= value && c > value && b > value) {
746 trace.push_back(
new Segment(ni, W, j,
'a',
'b',
'b',
'd', rec, value));
747 trace.push_back(
new Segment(ni, W, j,
'a',
'c',
'c',
'd', rec, value));
748 }
else if (a > value && d > value && c <= value && b <= value) {
749 trace.push_back(
new Segment(ni, W, j,
'a',
'b',
'a',
'c', rec, value));
750 trace.push_back(
new Segment(ni, W, j,
'b',
'd',
'c',
'd', rec, value));
763void ocpn_wx_quadratic_spline(
double a1,
double b1,
double a2,
double b2,
764 double a3,
double b3,
double a4,
double b4);
765void ocpn_wx_clear_stack();
766int ocpn_wx_spline_pop(
double *x1,
double *y1,
double *x2,
double *y2,
767 double *x3,
double *y3,
double *x4,
double *y4);
768void ocpn_wx_spline_push(
double x1,
double y1,
double x2,
double y2,
double x3,
769 double y3,
double x4,
double y4);
770static bool ocpn_wx_spline_add_point(
double x,
double y);
772#define half(z1, z2) ((z1 + z2) / 2.0)
777void ocpn_wx_quadratic_spline(
double a1,
double b1,
double a2,
double b2,
778 double a3,
double b3,
double a4,
double b4) {
780 double x1, y1, x2, y2, x3, y3, x4, y4;
782 ocpn_wx_clear_stack();
783 ocpn_wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
785 while (ocpn_wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
786 xmid = (double)half(x2, x3);
787 ymid = (double)half(y2, y3);
788 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
789 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
790 ocpn_wx_spline_add_point(x1, y1);
791 ocpn_wx_spline_add_point(xmid, ymid);
793 ocpn_wx_spline_push(xmid, ymid, (
double)half(xmid, x3),
794 (
double)half(ymid, y3), (
double)half(x3, x4),
795 (
double)half(y3, y4), x4, y4);
796 ocpn_wx_spline_push(x1, y1, (
double)half(x1, x2), (
double)half(y1, y2),
797 (
double)half(x2, xmid), (
double)half(y2, ymid), xmid,
806 double x1, y1, x2, y2, x3, y3, x4, y4;
809#define SPLINE_STACK_DEPTH 20
810static Stack ocpn_wx_spline_stack[SPLINE_STACK_DEPTH];
811static Stack *ocpn_wx_stack_top;
812static int ocpn_wx_stack_count;
814void ocpn_wx_clear_stack() {
815 ocpn_wx_stack_top = ocpn_wx_spline_stack;
816 ocpn_wx_stack_count = 0;
819void ocpn_wx_spline_push(
double x1,
double y1,
double x2,
double y2,
double x3,
820 double y3,
double x4,
double y4) {
821 ocpn_wx_stack_top->x1 = x1;
822 ocpn_wx_stack_top->y1 = y1;
823 ocpn_wx_stack_top->x2 = x2;
824 ocpn_wx_stack_top->y2 = y2;
825 ocpn_wx_stack_top->x3 = x3;
826 ocpn_wx_stack_top->y3 = y3;
827 ocpn_wx_stack_top->x4 = x4;
828 ocpn_wx_stack_top->y4 = y4;
830 ocpn_wx_stack_count++;
833int ocpn_wx_spline_pop(
double *x1,
double *y1,
double *x2,
double *y2,
834 double *x3,
double *y3,
double *x4,
double *y4) {
835 if (ocpn_wx_stack_count == 0)
return (0);
837 ocpn_wx_stack_count--;
838 *x1 = ocpn_wx_stack_top->x1;
839 *y1 = ocpn_wx_stack_top->y1;
840 *x2 = ocpn_wx_stack_top->x2;
841 *y2 = ocpn_wx_stack_top->y2;
842 *x3 = ocpn_wx_stack_top->x3;
843 *y3 = ocpn_wx_stack_top->y3;
844 *x4 = ocpn_wx_stack_top->x4;
845 *y4 = ocpn_wx_stack_top->y4;
849static bool ocpn_wx_spline_add_point(
double x,
double y) {
850 wxPoint *point =
new wxPoint;
853 ocpn_wx_spline_point_list.Append((wxObject *)point);
857void GenSpline(wxList *points) {
859 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
860 double x1, y1, x2, y2;
862 wxList::compatibility_iterator node = points->GetFirst();
867 p = (wxPoint *)node->GetData();
872 node = node->GetNext();
873 p = (wxPoint *)node->GetData();
877 cx1 = (double)((x1 + x2) / 2);
878 cy1 = (double)((y1 + y2) / 2);
879 cx2 = (double)((cx1 + x2) / 2);
880 cy2 = (double)((cy1 + y2) / 2);
882 ocpn_wx_spline_add_point(x1, y1);
884 while ((node = node->GetNext())
889 p = (wxPoint *)node->GetData();
894 cx4 = (double)(x1 + x2) / 2;
895 cy4 = (double)(y1 + y2) / 2;
896 cx3 = (double)(x1 + cx4) / 2;
897 cy3 = (double)(y1 + cy4) / 2;
899 ocpn_wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
903 cx2 = (double)(cx1 + x2) / 2;
904 cy2 = (double)(cy1 + y2) / 2;
907 ocpn_wx_spline_add_point(cx1, cy1);
908 ocpn_wx_spline_add_point(x2, y2);
912static void GenerateSpline(
int n, wxPoint points[])
915 for (
int i =0; i < n; i++)
917 list.Append((wxObject*)&points[i]);
923static void ClearSplineList()
925 wxList::compatibility_iterator node = ocpn_wx_spline_point_list.GetFirst();
928 wxPoint *point = (wxPoint *)node->GetData();
930 ocpn_wx_spline_point_list.Erase(node);
931 node = ocpn_wx_spline_point_list.GetFirst();
Factory class for creating and managing GRIB data visualizations.
A meteorological data grid from a GRIB (Gridded Binary) file.
int GetNj() const
Returns the number of points in the latitude (j) direction of the grid.
void getXY(int i, int j, double *x, double *y) const
Converts grid indices to longitude/latitude coordinates.
double GetValue(int i, int j) const
Returns the data value at a specific grid point.
int GetNi() const
Returns the number of points in the longitude (i) direction of the grid.
IsoLine(double val, double coeff, double offset, const GribRecord *rec)
Contains view parameters and status information for a chart display viewport.
double clon
Center longitude of the viewport in decimal degrees.
int m_projection_type
Chart projection type (PROJECTION_MERCATOR, etc.).
GRIB Data Visualization and Rendering Factory.
GRIB Display Settings Configuration Interface.
GRIB Isobar and Isoline Generation System.
@ PI_PROJECTION_EQUIRECTANGULAR
double PlugInGetDisplaySizeMM()
Gets physical display size in millimeters.
void GetCanvasPixLL(PlugIn_ViewPort *vp, wxPoint *pp, double lat, double lon)
Converts lat/lon to canvas physical pixel coordinates.
OpenGL Platform Abstraction Layer.