// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* // ** Copyright UCAR (c) 1990 - 2016 // ** University Corporation for Atmospheric Research (UCAR) // ** National Center for Atmospheric Research (NCAR) // ** Boulder, Colorado, USA // ** BSD licence applies - redistribution and use in source and binary // ** forms, with or without modification, are permitted provided that // ** the following conditions are met: // ** 1) If the software is modified to produce derivative works, // ** such modified software should be clearly marked, so as not // ** to confuse it with the version available from UCAR. // ** 2) Redistributions of source code must retain the above copyright // ** notice, this list of conditions and the following disclaimer. // ** 3) Redistributions in binary form must reproduce the above copyright // ** notice, this list of conditions and the following disclaimer in the // ** documentation and/or other materials provided with the distribution. // ** 4) Neither the name of UCAR nor the names of its contributors, // ** if any, may be used to endorse or promote products derived from // ** this software without specific prior written permission. // ** DISCLAIMER: THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS // ** OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED // ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* ////////////////////////////////////////////////////////// // Symprod_add.cc // // Add routines for symbolic product class // // Mike Dixon, from Nancy Rehak // RAP, NCAR, Boulder, CO, 80307, USA // // Dec 1999 // ////////////////////////////////////////////////////////// #include #include #include #include #include #include #include using namespace std; /////////////////////////////////////////////////////// // Add a generic object void Symprod::addObject(SymprodObj *obj, int obj_type, bbox_t &bbox) { _objs.push_back(obj); _objTypes.push_back(obj_type); _prodProps.num_objs++; updateBbox(_prodProps.bounding_box, bbox); } /////////////////////////////////////////////////////// // Add a SYMPROD text object. void Symprod::addText(const char *text_string, double lat, double lon, const char *color, const char *background_color, int offset_x /* = 0*/, int offset_y /* = 0*/, vert_align_t vert_alignment /* = VERT_ALIGN_CENTER*/, horiz_align_t horiz_alignment /* = HORIZ_ALIGN_CENTER*/, int font_size /* = 0*/, font_style_t font_style /* = TEXT_NORM*/, const char *fontname /* = NULL*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid bbox_t bbox; initBbox(bbox); updateBbox(bbox, lat, lon); wpt_t centroid; centroid.lat = lat; centroid.lon = lon; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_TEXT; hdr.object_id = object_id; hdr.num_bytes = sizeof(text_props_t) + strlen(text_string) + 1; hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); STRncopy(hdr.background_color, background_color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props text_props_t props; MEM_zero(props); props.origin = centroid; props.offset.x = offset_x; props.offset.y = offset_y; props.vert_alignment = vert_alignment; props.horiz_alignment = horiz_alignment; props.font_size = font_size; props.font_style = font_style; props.length = strlen(text_string); if (fontname == NULL) { STRncopy(props.fontname, "None", SYMPROD_FONT_NAME_LEN); } else { STRncopy(props.fontname, fontname, SYMPROD_FONT_NAME_LEN); } // create a text object SymprodText *obj = new SymprodText(hdr, props, text_string); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ////////////////////////////////////////////////////////// // Add a polyline object. // void Symprod::addPolyline(int npoints, const wpt_t *pts, const char *color, linetype_t linetype /* = LINETYPE_SOLID*/, int linewidth /* = 1*/, capstyle_t capstyle /* = CAPSTYLE_BUTT*/, joinstyle_t joinstyle /* = JOINSTYLE_BEVEL*/, bool close_flag /* = false*/, fill_t fill /* = FILL_NONE*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid bbox_t bbox; initBbox(bbox); const wpt_t *pt = pts; for (int ipt = 0; ipt < npoints; ipt++, pt++) { if (pt->lat != WPT_PENUP && pt->lon != WPT_PENUP) updateBbox(bbox, pt->lat, pt->lon); } wpt_t centroid; centroid.lat = (bbox.min_lat + bbox.max_lat) / 2.0; centroid.lon = (bbox.min_lon + bbox.max_lon) / 2.0; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_POLYLINE; hdr.object_id = object_id; hdr.num_bytes = sizeof(polyline_props_t) + npoints * sizeof(wpt_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props polyline_props_t props; MEM_zero(props); props.close_flag = close_flag; props.fill = fill; props.linetype = linetype; props.linewidth = linewidth; props.capstyle = capstyle; props.joinstyle = joinstyle; props.line_interp = LINE_INTERP_STRAIGHT; props.num_points = npoints; // create a polyline object SymprodPolyline *obj = new SymprodPolyline(hdr, props, pts); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } void Symprod::addPolyline(int npoints, const wpt_t *pts, double centroid_lat, double centroid_lon, const char *color, linetype_t linetype /* = LINETYPE_SOLID*/, int linewidth /* = 1*/, capstyle_t capstyle /* = CAPSTYLE_BUTT*/, joinstyle_t joinstyle /* = JOINSTYLE_BEVEL*/, bool close_flag /* = false*/, fill_t fill /* = FILL_NONE*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // set centroid wpt_t centroid; centroid.lat = centroid_lat; centroid.lon = centroid_lon; // compute bounding box bbox_t bbox; initBbox(bbox); const wpt_t *pt = pts; for (int ipt = 0; ipt < npoints; ipt++, pt++) { if (pt->lat != WPT_PENUP && pt->lon != WPT_PENUP) updateBbox(bbox, pt->lat, pt->lon); } // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_POLYLINE; hdr.object_id = object_id; hdr.num_bytes = sizeof(polyline_props_t) + npoints * sizeof(wpt_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props polyline_props_t props; MEM_zero(props); props.close_flag = close_flag; props.fill = fill; props.linetype = linetype; props.linewidth = linewidth; props.capstyle = capstyle; props.joinstyle = joinstyle; props.line_interp = LINE_INTERP_STRAIGHT; props.num_points = npoints; // create a polyline object SymprodPolyline *obj = new SymprodPolyline(hdr, props, pts); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ////////////////////////////////////////////////////////// // Add a iconline object. // void Symprod::addIconline(double origin_lat, double origin_lon, int npoints, const ppt_t *pts, const char *color, linetype_t linetype /* = LINETYPE_SOLID*/, int linewidth /* = 1*/, capstyle_t capstyle /* = CAPSTYLE_BUTT*/, joinstyle_t joinstyle /* = JOINSTYLE_BEVEL*/, bool close_flag /* = false*/, fill_t fill /* = FILL_NONE*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // bounding box - icon line probably does not span more that // 1 degree each way bbox_t bbox; initBbox(bbox); updateBbox(bbox, origin_lat - 1.0, origin_lon - 1.0); updateBbox(bbox, origin_lat - 1.0, origin_lon + 1.0); updateBbox(bbox, origin_lat + 1.0, origin_lon - 1.0); updateBbox(bbox, origin_lat + 1.0, origin_lon + 1.0); wpt_t centroid; centroid.lat = origin_lat; centroid.lon = origin_lon; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_ICONLINE; hdr.object_id = object_id; hdr.num_bytes = sizeof(iconline_props_t) + npoints * sizeof(ppt_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props iconline_props_t props; MEM_zero(props); props.origin.lat = origin_lat; props.origin.lon = origin_lon; props.close_flag = close_flag; props.fill = fill; props.linetype = linetype; props.linewidth = linewidth; props.capstyle = capstyle; props.joinstyle = joinstyle; props.line_interp = LINE_INTERP_STRAIGHT; props.num_points = npoints; // create a iconline object SymprodIconline *obj = new SymprodIconline(hdr, props, pts); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ///////////////////////////////////////////////////////////////// // Add stroked icons. void Symprod::addStrokedIcons(const char *color, int num_icon_pts, const ppt_t *icon_pts, int num_icons, const wpt_t *icon_origins, int object_id /* = 0*/, int detail_level /* = 0*/, int linewidth /* = 1*/ ) { // compute bounding box & centroid bbox_t bbox; initBbox(bbox); for (int ipt = 0; ipt < num_icons; ipt++) { updateBbox(bbox, icon_origins[ipt].lat, icon_origins[ipt].lon); } wpt_t centroid; centroid.lat = (bbox.min_lat + bbox.max_lat) / 2.0; centroid.lon = (bbox.min_lon + bbox.max_lon) / 2.0; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_STROKED_ICON; hdr.object_id = object_id; hdr.num_bytes = sizeof(stroked_icon_props_t) + num_icon_pts * sizeof(ppt_t) + num_icons * sizeof(wpt_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props stroked_icon_props_t props; MEM_zero(props); props.num_icon_pts = num_icon_pts; props.num_icons = num_icons; props.linewidth = linewidth; // create a stroked icon object SymprodStrokedIcon *obj = new SymprodStrokedIcon(hdr, props, icon_pts, icon_origins); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ///////////////////////////////////////////////////////////////// // Add named icons. void Symprod::addNamedIcons(const char *name, const char *color, int num_icons, const wpt_t *icon_origins, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid bbox_t bbox; initBbox(bbox); for (int ipt = 0; ipt < num_icons; ipt++) { updateBbox(bbox, icon_origins[ipt].lat, icon_origins[ipt].lon); } wpt_t centroid; centroid.lat = (bbox.min_lat + bbox.max_lat) / 2.0; centroid.lon = (bbox.min_lon + bbox.max_lon) / 2.0; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_NAMED_ICON; hdr.object_id = object_id; hdr.num_bytes = sizeof(named_icon_props_t) + num_icons * sizeof(wpt_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props named_icon_props_t props; MEM_zero(props); STRncopy(props.name, name, SYMPROD_ICON_NAME_LEN); props.num_icons = num_icons; // create a named icon object SymprodNamedIcon *obj = new SymprodNamedIcon(hdr, props, icon_origins); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ///////////////////////////////////////////////////////////////// // Add bitmap icons. void Symprod::addBitmapIcons(const char *color, int num_icons, const wpt_t *icon_origins, int bitmap_x_dim, int bitmap_y_dim, const ui08 *bitmap, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid bbox_t bbox; initBbox(bbox); for (int ipt = 0; ipt < num_icons; ipt++) { updateBbox(bbox, icon_origins[ipt].lat, icon_origins[ipt].lon); } wpt_t centroid; centroid.lat = (bbox.min_lat + bbox.max_lat) / 2.0; centroid.lon = (bbox.min_lon + bbox.max_lon) / 2.0; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_BITMAP_ICON; hdr.object_id = object_id; hdr.num_bytes = (sizeof(bitmap_icon_props_t) + (num_icons * sizeof(wpt_t)) + (bitmap_x_dim * bitmap_y_dim * sizeof(ui08))); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props bitmap_icon_props_t props; MEM_zero(props); props.bitmap_x_dim = bitmap_x_dim; props.bitmap_y_dim = bitmap_y_dim; props.num_icons = num_icons; // create a bitmap icon object SymprodBitmapIcon *obj = new SymprodBitmapIcon(hdr, props, icon_origins, bitmap); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ////////////////////////////////////////////////////////// // Add an arc object. // void Symprod::addArc(double origin_lat, double origin_lon, double radius_x, double radius_y, const char *color, bool radii_in_pixels /* = false = same units as origin */, double angle1 /* = 0.0*/, double angle2 /* = 360.0*/, double axis_rotation /* = 0.0*/, int nsegments /* = 90*/, linetype_t linetype /* = LINETYPE_SOLID*/, int linewidth /* = 1*/, capstyle_t capstyle /* = CAPSTYLE_BUTT*/, joinstyle_t joinstyle /* = JOINSTYLE_BEVEL*/, fill_t fill /* = FILL_NONE*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid double maxr = MAX(radius_x, radius_y); double dlat = maxr * DEG_PER_KM_AT_EQ; double dlon = dlat * cos(origin_lat * RAD_PER_DEG); bbox_t bbox; bbox.min_lat = origin_lat - dlat; bbox.max_lat = origin_lat + dlat; bbox.min_lon = origin_lon - dlon; bbox.max_lon = origin_lon + dlon; wpt_t origin; origin.lat = origin_lat; origin.lon = origin_lon; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_ARC; hdr.object_id = object_id; hdr.num_bytes = sizeof(arc_props_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = origin; // load props arc_props_t props; MEM_zero(props); props.origin = origin; props.radius_x = radius_x; props.radius_y = radius_y; props.angle1 = angle1; props.angle2 = angle2; props.axis_rotation = axis_rotation; props.linetype = linetype; props.linewidth = linewidth; props.fill = fill; props.capstyle = capstyle; props.joinstyle = joinstyle; props.nsegments = nsegments; props.radii_in_pixels = (int) radii_in_pixels; // create a arc object SymprodArc *obj = new SymprodArc(hdr, props); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ////////////////////////////////////////////////////////// // Add a rectangle object. // void Symprod::addRectangle(double origin_lat, double origin_lon, double height, double width, const char *color, linetype_t linetype /* = LINETYPE_SOLID*/, int linewidth /* = 1*/, capstyle_t capstyle /* = CAPSTYLE_BUTT*/, joinstyle_t joinstyle /* = JOINSTYLE_BEVEL*/, fill_t fill /* = FILL_NONE*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box & centroid double dlat = height * DEG_PER_KM_AT_EQ; double dlon = width * DEG_PER_KM_AT_EQ * cos(origin_lat * RAD_PER_DEG); bbox_t bbox; bbox.min_lat = origin_lat; bbox.max_lat = origin_lat + dlat; bbox.min_lon = origin_lon; bbox.max_lon = origin_lon + dlon; wpt_t origin; origin.lat = origin_lat; origin.lon = origin_lon; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_RECTANGLE; hdr.object_id = object_id; hdr.num_bytes = sizeof(rectangle_props_t); hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); hdr.centroid = origin; // load props rectangle_props_t props; MEM_zero(props); props.origin = origin; props.height = height; props.width = width; props.linetype = linetype; props.linewidth = linewidth; props.fill = fill; props.capstyle = capstyle; props.joinstyle = joinstyle; // create a rectangle object SymprodRectangle *obj = new SymprodRectangle(hdr, props); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } ///////////////////////////////////////////////////////// // Add a chunk object. void Symprod::addChunk(double min_lat, double min_lon, double max_lat, double max_lon, int chunk_type, int nbytes_chunk, const void *data, const char *color, const char *background_color, int user_info /* = 0*/, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute bounding box and centroid bbox_t bbox; bbox.min_lat = min_lat; bbox.max_lat = max_lat; bbox.min_lon = min_lon; bbox.max_lon = max_lon; wpt_t centroid; centroid.lat = (max_lat + min_lat) / 2.0; centroid.lon = (max_lon + min_lon) / 2.0; // load hdr obj_hdr_t hdr; MEM_zero(hdr); hdr.object_type = OBJ_CHUNK; hdr.object_id = object_id; hdr.num_bytes = sizeof(chunk_props_t) + nbytes_chunk; hdr.detail_level = detail_level; STRncopy(hdr.color, color, SYMPROD_COLOR_LEN); STRncopy(hdr.background_color, background_color, SYMPROD_COLOR_LEN); hdr.centroid = centroid; // load props chunk_props_t props; MEM_zero(props); props.chunk_type = chunk_type; props.user_info = user_info; props.nbytes_chunk = nbytes_chunk; // create a chunk object SymprodChunk *obj = new SymprodChunk(hdr, props, data); // add it, updating the product bounding box addObject(obj, hdr.object_type, bbox); } /////////////////////////////////////////////////////////////////////// // Add an arrow object given start and end points // head_len_km: in km // head_half_angle: in deg void Symprod::addArrowBothPts(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double end_lat, double end_lon, double head_len_km, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double length, dirn; PJGLatLon2RTheta(start_lat, start_lon, end_lat, end_lon, &length, &dirn); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_km, head_half_angle, object_id, detail_level); } void Symprod::addArrowBothPts(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double end_lat, double end_lon, int head_len_pixels, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double length, dirn; PJGLatLon2RTheta(start_lat, start_lon, end_lat, end_lon, &length, &dirn); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_pixels, head_half_angle, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // Add an arrow object given start pt, length, dirn // head_len_km: in km // head_half_angle: in deg void Symprod::addArrowStartPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double length, double dirn, double head_len_km, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double end_lat, end_lon; PJGLatLonPlusRTheta(start_lat, start_lon, length, dirn, &end_lat, &end_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_km, head_half_angle, object_id, detail_level); } void Symprod::addArrowStartPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double length, double dirn, int head_len_pixels, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double end_lat, end_lon; PJGLatLonPlusRTheta(start_lat, start_lon, length, dirn, &end_lat, &end_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_pixels, head_half_angle, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // Add an arrow object given end pt, length, dirn // head_len_km: in km // head_half_angle: in deg void Symprod::addArrowEndPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double end_lat, double end_lon, double length, double dirn, double head_len_km, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double start_lat, start_lon; PJGLatLonPlusRTheta(end_lat, end_lon, length, dirn + 180.0, &start_lat, &start_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_km, head_half_angle, object_id, detail_level); } void Symprod::addArrowEndPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double end_lat, double end_lon, double length, double dirn, int head_len_pixels, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double start_lat, start_lon; PJGLatLonPlusRTheta(end_lat, end_lon, length, dirn + 180.0, &start_lat, &start_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_pixels, head_half_angle, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // Add an arrow object given mid pt, length, dirn // head_len_km: in km // head_half_angle: in deg void Symprod::addArrowMidPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double mid_lat, double mid_lon, double length, double dirn, double head_len_km, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double start_lat, start_lon; double end_lat, end_lon; PJGLatLonPlusRTheta(mid_lat, mid_lon, length / 2.0, dirn, &end_lat, &end_lon); PJGLatLonPlusRTheta(mid_lat, mid_lon, length / 2.0, dirn + 180.0, &start_lat, &start_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_km, head_half_angle, object_id, detail_level); } void Symprod::addArrowMidPt(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double mid_lat, double mid_lon, double length, double dirn, int head_len_pixels, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { double start_lat, start_lon; double end_lat, end_lon; PJGLatLonPlusRTheta(mid_lat, mid_lon, length / 2.0, dirn, &end_lat, &end_lon); PJGLatLonPlusRTheta(mid_lat, mid_lon, length / 2.0, dirn + 180.0, &start_lat, &start_lon); addArrow(color, linetype, linewidth, capstyle, joinstyle, start_lat, start_lon, end_lat, end_lon, length, dirn, head_len_pixels, head_half_angle, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // addArrow() // // Add an generic arrow object given the start and end lat, length and dirn. // // head_len_km: in km // head_half_angle: in deg void Symprod::addArrow(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double end_lat, double end_lon, double length, double dirn, double head_len_km, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute the arrow points wpt_t arrow[5]; arrow[0].lat = start_lat; arrow[0].lon = start_lon; arrow[1].lat = end_lat; arrow[1].lon = end_lon; PJGLatLon2RTheta(start_lat, start_lon, end_lat, end_lon, &length, &dirn); double angle = dirn + 180.0 + head_half_angle; double lat, lon; PJGLatLonPlusRTheta(end_lat, end_lon, head_len_km, angle, &lat, &lon); arrow[2].lat = lat; arrow[2].lon = lon; arrow[3].lat = end_lat; arrow[3].lon = end_lon; angle = dirn + 180.0 - head_half_angle; PJGLatLonPlusRTheta(end_lat, end_lon, head_len_km, angle, &lat, &lon); arrow[4].lat = lat; arrow[4].lon = lon; // add polyline object addPolyline(5, arrow, color, linetype, linewidth, capstyle, joinstyle, FALSE, FILL_NONE, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // addArrow() // // Add an generic arrow object given the start and end lat, length and dirn // // head_len_pixels: in pixels (icon space) // head_half_angle: in deg void Symprod::addArrow(const char *color, linetype_t linetype, int linewidth, capstyle_t capstyle, joinstyle_t joinstyle, double start_lat, double start_lon, double end_lat, double end_lon, double length, double dirn, int head_len_pixels, double head_half_angle, int object_id /* = 0*/, int detail_level /* = 0*/ ) { // compute the arrow end points wpt_t shaft[2]; shaft[0].lat = start_lat; shaft[0].lon = start_lon; shaft[1].lat = end_lat; shaft[1].lon = end_lon; // add polyline for shaft addPolyline(2, shaft, color, linetype, linewidth, capstyle, joinstyle, FALSE, FILL_NONE, object_id, detail_level); // compute direction and head angles PJGLatLon2RTheta(start_lat, start_lon, end_lat, end_lon, &length, &dirn); double angle1 = 270 - dirn - head_half_angle; double angle2 = 270 - dirn + head_half_angle; // compute head icon line ppt_t head[3]; head[0].x = (int) ((double) head_len_pixels * cos(angle1 * DEG_TO_RAD) + 0.5); head[0].y = (int) ((double) head_len_pixels * sin(angle1 * DEG_TO_RAD) + 0.5); head[1].x = 0; head[1].y = 0; head[2].x = (int) ((double) head_len_pixels * cos(angle2 * DEG_TO_RAD) + 0.5); head[2].y = (int) ((double) head_len_pixels * sin(angle2 * DEG_TO_RAD) + 0.5); // add head icon line addIconline(end_lat, end_lon, 3, head, color, linetype, linewidth, capstyle, joinstyle, FALSE, FILL_NONE, object_id, detail_level); } /////////////////////////////////////////////////////////////////////// // addWindBarb() // // Add an wind barb object // // speed //knots // dir //degrees // station_posn_circle_radius //pixels // wind_barb_line_width //pixels // wind_ticks_angle_to_shaft //degrees // wind_barb_tick_len //pixels // wind_barb_shaft_len //pixels void Symprod::addWindBarb(double lat, double lon, const char* color, double speed, double dir, int station_posn_circle_radius, int wind_barb_line_width, double wind_ticks_angle_to_shaft, double wind_barb_tick_len, int wind_barb_shaft_len, int detail_level) { // abort if wind value is too high if (speed > 350.0) { return; } // add circle to show location if (station_posn_circle_radius > 0) { addArc(lat, lon, station_posn_circle_radius, station_posn_circle_radius, color, true, 0, 360.0, 0.0, 60, LINETYPE_SOLID, 1, CAPSTYLE_BUTT, JOINSTYLE_BEVEL, FILL_NONE, 0, detail_level); } // return now if speed below 2.5 if (speed < 2.5) { return; } // add shaft double dirrad = dir * DEG_TO_RAD; double cosdir = cos(dirrad); double sindir = sin(dirrad); ppt_t shaft[2]; shaft[0].x = 0; shaft[0].y = 0; shaft[1].x = (int) floor(wind_barb_shaft_len * sindir + 0.5); shaft[1].y = (int) floor(wind_barb_shaft_len * cosdir + 0.5); addIconline(lat, lon, 2, shaft, color, LINETYPE_SOLID, wind_barb_line_width, CAPSTYLE_BUTT, JOINSTYLE_BEVEL, false, FILL_NONE, 0, detail_level); // add flags for each 50 kts double tick_rel_angle; if (lat >= 0.0) { tick_rel_angle = wind_ticks_angle_to_shaft; } else { tick_rel_angle = -wind_ticks_angle_to_shaft; } double tick_rad = dirrad + tick_rel_angle * DEG_TO_RAD; double tick_len = wind_barb_tick_len; double tick_point_offset_x = tick_len * sin(tick_rad); double tick_point_offset_y = tick_len * cos(tick_rad); double tick_spacing; if (speed < 150.0) { tick_spacing = wind_barb_shaft_len / 7.5; } else { tick_spacing = wind_barb_shaft_len / 10.0; } if (tick_spacing < 3.0) { tick_spacing = 3.0; } double tick_dx = tick_spacing * sindir; double tick_dy = tick_spacing * cosdir; // Add the speed markings double speed_left = speed; double shaft_left = wind_barb_shaft_len; double x_inner = shaft_left * sindir; double y_inner = shaft_left * cosdir; // flags for each 50 kts while (speed_left >= 47.5) { double x_outer = x_inner; double y_outer = y_inner; x_inner -= tick_dx; y_inner -= tick_dy; double x_point = x_outer + tick_point_offset_x; double y_point = y_outer + tick_point_offset_y; ppt_t flag[3]; flag[0].x = (int) floor(x_outer + 0.5); flag[0].y = (int) floor(y_outer + 0.5); flag[1].x = (int) floor(x_point + 0.5); flag[1].y = (int) floor(y_point + 0.5); flag[2].x = (int) floor(x_inner + 0.5); flag[2].y = (int) floor(y_inner + 0.5); addIconline(lat, lon, 3, flag, color, LINETYPE_SOLID, wind_barb_line_width, CAPSTYLE_BUTT, JOINSTYLE_BEVEL, true, FILL_SOLID, 0, detail_level); speed_left -= 50.0; shaft_left -= tick_spacing; } // while (speed_left >= 47.5) if (speed > 47.5) { x_inner -= tick_dx / 2.0; y_inner -= tick_dy / 2.0; } while (speed_left >= 7.5) { double x_outer = x_inner; double y_outer = y_inner; x_inner -= tick_dx; y_inner -= tick_dy; double x_point = x_outer + tick_point_offset_x; double y_point = y_outer + tick_point_offset_y; ppt_t full_tick[2]; full_tick[0].x = (int) floor(x_outer + 0.5); full_tick[0].y = (int) floor(y_outer + 0.5); full_tick[1].x = (int) floor(x_point + 0.5); full_tick[1].y = (int) floor(y_point + 0.5); addIconline(lat, lon, 2, full_tick, color, LINETYPE_SOLID, wind_barb_line_width, CAPSTYLE_BUTT, JOINSTYLE_BEVEL, false, FILL_NONE, 0, detail_level); speed_left -= 10.0; shaft_left -= tick_spacing; } // while (speed_left >= 7.5) // half ticks for each 5 kts // single 5-kt barb is rendered in from the end if (speed < 7.5) { x_inner -= tick_dx; y_inner -= tick_dy; } if (speed_left >= 2.5) { double x_point = x_inner + tick_point_offset_x / 2.0; double y_point = y_inner + tick_point_offset_y / 2.0; ppt_t half_tick[2]; half_tick[0].x = (int) floor(x_inner + 0.5); half_tick[0].y = (int) floor(y_inner + 0.5); half_tick[1].x = (int) floor(x_point + 0.5); half_tick[1].y = (int) floor(y_point + 0.5); addIconline(lat, lon, 2, half_tick, color, LINETYPE_SOLID, wind_barb_line_width, CAPSTYLE_BUTT, JOINSTYLE_BEVEL, false, FILL_NONE, 0, detail_level); } // if (speed_left >= 5) }