void BoatDialog::OnPaintCrossOverChart(wxPaintEvent& event) { wxWindow *window = dynamic_cast<wxWindow*>(event.GetEventObject()); if(!window) return; wxGCDC dc(window); dc.SetBackgroundMode(wxTRANSPARENT); long index = SelectedPolar(); bool polar = !m_cPlotType->GetSelection(); int w, h; m_CrossOverChart->GetSize( &w, &h); dc.SetPen(wxPen(wxColor(0, 0, 0))); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetTextForeground(wxColour(0, 55, 75)); bool full = m_cbFullPlot->GetValue(); double scale; int xc = full ? w / 2 : 0; if(polar) { scale = wxMin(full ? w/2 : w, h/2) / 40.0; } for(double VW = 0; VW < 40; VW += 10) { if(polar) { dc.DrawCircle(xc, h/2, VW * scale); dc.DrawText(wxString::Format(_T("%.0f"), VW), xc, h/2+(int)VW*scale); } else { int y = h - VW * h / 40; dc.DrawLine(0, y, w, y); dc.DrawText(wxString::Format(_T("%.0f"), VW), 0, y); } } for(double H = 0; H < 180; H += 10) { if(polar) { double x = scale*sin(deg2rad(H)); double y = scale*cos(deg2rad(H)); if(H < 180) dc.DrawLine(xc - x, h/2 + y, xc + x, h/2 - y); wxString str = wxString::Format(_T("%.0f"), H); int sw, sh; dc.GetTextExtent(str, &sw, &sh); dc.DrawText(str, xc + .9*x - sw/2, h/2 - .9*y - sh/2); } else { int x = H * w / 180; dc.DrawLine(x, 0, x, h); dc.DrawText(wxString::Format(_T("%.0f"), H), x, 0); } } wxColour colors[] = {*wxRED, *wxGREEN, *wxBLUE, *wxCYAN, *wxYELLOW, wxColour(255, 0, 255)}; int c = 0; for(unsigned int i=0; i<m_Boat.Polars.size(); i++) { bool bold = i == index; // dc.SetPen(wxPen(colors[c], bold ? 1 : 3)); dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxColour(colors[c].Red(), colors[c].Green(), colors[c].Blue(), bold ? 230 : 60)); if(++c == (sizeof colors) / (sizeof *colors)) c = 0; bool tri = true; TESStesselator *tess = m_Boat.Polars[i].CrossOverRegion.Tesselate(tri); if(!tess) continue; const float* verts = tessGetVertices(tess); // const int* vinds = tessGetVertexIndices(tess); const int* elems = tessGetElements(tess); // const int nverts = tessGetVertexCount(tess); const int nelems = tessGetElementCount(tess); // Draw polygons. for (int i = 0; i < nelems; ++i) { if(tri) { const int* p = &elems[i*3]; wxPoint points[3]; for (unsigned j = 0; j < 3 && p[j] != TESS_UNDEF; ++j) { double H = verts[p[j]*2+0]; double VW = verts[p[j]*2+1]; points[j] = wxPoint(H * w / 180, h - VW * h / 40); } if(polar) { int count[3] = {CalcPolarPoints(points[0], points[1]), CalcPolarPoints(points[1], points[2]), CalcPolarPoints(points[2], points[0])}; wxPoint *pts = new wxPoint[count[0] + count[1] + count[2]]; int c = 0; for(int j = 0; j<3; j++) { int jp1 = j+1 == 3 ? 0 : j+1; for(int k=0; k<count[j]; k++) { double d = (double)k / count[j]; double px = points[j].x * (1-d) + points[jp1].x * d; double py = points[j].y * (1-d) + points[jp1].y * d; double H = px / w * 180; double VW = (h - py) / h * 40; pts[c++] = wxPoint(xc + scale*VW*sin(deg2rad(H)), h/2 - scale*VW*cos(deg2rad(H))); } } dc.DrawPolygon(c, pts); if(full) { for(int j = 0; j<c; j++) pts[j].x = 2*xc - pts[j].x; dc.DrawPolygon(c, pts); } delete [] pts; } else { dc.DrawPolygon(3, points); } } else { int b = elems[i*2]; int n = elems[i*2+1]; wxPoint pl; for(int j = 0; j<=n; j++) { int k = j < n ? j : 0; float H = verts[2*(b + k)+0], VW = verts[2*(b + k)+1]; wxPoint p0; if(polar) p0 = wxPoint(xc + scale*VW*sin(deg2rad(H)), h/2 - scale*VW*cos(deg2rad(H))); else p0 = wxPoint(H * w / 180, h - VW * h / 40); if(j > 0) dc.DrawLine(pl, p0); pl = p0; } } } tessDeleteTess(tess); } }
/* Purpose: calculate the apparent longitude of the sun (degrees) */ double calcSunApparentLong(double t) { return calcSunTrueLong(t) - 0.00569 - 0.00478 * sin(deg2rad(125.04-1934.136*t)); }
/* Purpose: calculate the declination of the sun (degrees) */ double calcSunDeclination(double t) { return rad2deg(asin(sin(deg2rad(calcObliquityCorrection(t))) * sin(deg2rad(calcSunApparentLong(t))))); }
/* compute apparent wind speed from boat speed and true wind */ double Polar::VelocityApparentWind(double VB, double W, double VW) { return sqrt(VW*VW + VB*VB + 2*VW*VB*cos(deg2rad(W))); /* law of cosines, W is flipped by 180 */ }
double PolarMeasurement::VW() const { return sqrt(VA*VA + VB*VB - 2*VA*VB*cos(deg2rad(A))); }
AffineTransform& AffineTransform::skew(double angleX, double angleY) { return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY))); }
AffineTransform& AffineTransform::skewY(double angle) { return shear(0, tan(deg2rad(angle))); }
void do_paint_myposition() { int pixel_x, pixel_y, x,y; float lat, lon; GdkColor color; GdkGC *gc; GError *error = NULL; gc = gdk_gc_new(pixmap); color.green = 60000; color.blue = 0; color.red = 10000; gdk_gc_set_rgb_fg_color(gc, &color); if(!myposition_icon) { myposition_icon = gdk_pixbuf_new_from_file_at_size ( PACKAGE_PIXMAPS_DIR "/tangogps-myposition.png", 36,36, &error); if (error) { g_print ("%s(): loading pixbuf failure. %s\n", __FUNCTION__, error->message); g_error_free (error); } } if (pixmap && !gc_map) gc_map = gdk_gc_new(pixmap); printf("*** %s(): \n",__PRETTY_FUNCTION__); lat = deg2rad(global_myposition.lat); lon = deg2rad(global_myposition.lon); pixel_x = lon2pixel(global_zoom, lon); pixel_y = lat2pixel(global_zoom, lat); x = pixel_x - global_x; y = pixel_y - global_y; printf("%d %d %f %f\n",x,y,lat,lon); //здесь рисуется жирная центральная точка позиции if(!myposition_icon) { gdk_draw_arc ( pixmap, gc, TRUE, x-4, y-4, 8,8, 0,23040); } else { gdk_draw_pixbuf ( pixmap, gc_map, myposition_icon, 0,0, x,y-36, 36,36, GDK_RGB_DITHER_NONE, 0, 0); gtk_widget_queue_draw_area ( map_drawable, x, y-36, 36,36); } printf("MYPOSITION: lat %f - lon %f\n",lat, lon); }
template <typename PointInT, typename PointOutT, typename PointRFT> bool pcl::UniqueShapeContext<PointInT, PointOutT, PointRFT>::initCompute () { if (!Feature<PointInT, PointOutT>::initCompute ()) { PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ()); return (false); } // Default LRF estimation alg: SHOTLocalReferenceFrameEstimation typename SHOTLocalReferenceFrameEstimation<PointInT, PointRFT>::Ptr lrf_estimator(new SHOTLocalReferenceFrameEstimation<PointInT, PointRFT>()); lrf_estimator->setRadiusSearch (local_radius_); lrf_estimator->setInputCloud (input_); lrf_estimator->setIndices (indices_); if (!fake_surface_) lrf_estimator->setSearchSurface(surface_); if (!FeatureWithLocalReferenceFrames<PointInT, PointRFT>::initLocalReferenceFrames (indices_->size (), lrf_estimator)) { PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ()); return (false); } if (search_radius_< min_radius_) { PCL_ERROR ("[pcl::%s::initCompute] search_radius_ must be GREATER than min_radius_.\n", getClassName ().c_str ()); return (false); } // Update descriptor length descriptor_length_ = elevation_bins_ * azimuth_bins_ * radius_bins_; // Compute radial, elevation and azimuth divisions float azimuth_interval = 360.0f / static_cast<float> (azimuth_bins_); float elevation_interval = 180.0f / static_cast<float> (elevation_bins_); // Reallocate divisions and volume lut radii_interval_.clear (); phi_divisions_.clear (); theta_divisions_.clear (); volume_lut_.clear (); // Fills radii interval based on formula (1) in section 2.1 of Frome's paper radii_interval_.resize (radius_bins_ + 1); for (size_t j = 0; j < radius_bins_ + 1; j++) radii_interval_[j] = static_cast<float> (exp (log (min_radius_) + ((static_cast<float> (j) / static_cast<float> (radius_bins_)) * log (search_radius_/min_radius_)))); // Fill theta didvisions of elevation theta_divisions_.resize (elevation_bins_+1); for (size_t k = 0; k < elevation_bins_+1; k++) theta_divisions_[k] = static_cast<float> (k) * elevation_interval; // Fill phi didvisions of elevation phi_divisions_.resize (azimuth_bins_+1); for (size_t l = 0; l < azimuth_bins_+1; l++) phi_divisions_[l] = static_cast<float> (l) * azimuth_interval; // LookUp Table that contains the volume of all the bins // "phi" term of the volume integral // "integr_phi" has always the same value so we compute it only one time float integr_phi = pcl::deg2rad (phi_divisions_[1]) - pcl::deg2rad (phi_divisions_[0]); // exponential to compute the cube root using pow float e = 1.0f / 3.0f; // Resize volume look up table volume_lut_.resize (radius_bins_ * elevation_bins_ * azimuth_bins_); // Fill volumes look up table for (size_t j = 0; j < radius_bins_; j++) { // "r" term of the volume integral float integr_r = (radii_interval_[j+1]*radii_interval_[j+1]*radii_interval_[j+1] / 3) - (radii_interval_[j]*radii_interval_[j]*radii_interval_[j]/ 3); for (size_t k = 0; k < elevation_bins_; k++) { // "theta" term of the volume integral float integr_theta = cosf (deg2rad (theta_divisions_[k])) - cosf (deg2rad (theta_divisions_[k+1])); // Volume float V = integr_phi * integr_theta * integr_r; // Compute cube root of the computed volume commented for performance but left // here for clarity // float cbrt = pow(V, e); // cbrt = 1 / cbrt; for (size_t l = 0; l < azimuth_bins_; l++) // Store in lut 1/cbrt //volume_lut_[ (l*elevation_bins_*radius_bins_) + k*radius_bins_ + j ] = cbrt; volume_lut_[(l*elevation_bins_*radius_bins_) + k*radius_bins_ + j] = 1.0f / powf (V, e); } } return (true); }
void TacticsInstrument_AppTrueWindAngle::DrawForeground(wxGCDC* dc) { wxPoint points[4]; double data; double val; double value; // The default foreground is the arrow used in most dials wxColour cl; GetGlobalColor(_T("DASH2"), &cl); wxPen pen1; pen1.SetStyle(wxSOLID); pen1.SetColour(cl); pen1.SetWidth(2); dc->SetPen(pen1); GetGlobalColor(_T("DASH1"), &cl); wxBrush brush1; brush1.SetStyle(wxSOLID); brush1.SetColour(cl); dc->SetBrush(brush1); dc->DrawCircle(m_cx, m_cy, m_radius / 8); /*True Wind*/ dc->SetPen(*wxTRANSPARENT_PEN); GetGlobalColor(_T("BLUE3"), &cl); wxBrush brush2; brush2.SetStyle(wxSOLID); brush2.SetColour(cl); dc->SetBrush(brush2); /* this is fix for a +/-180° round instrument, when m_MainValue is supplied as <0..180><L | R> * for example TWA & AWA */ if (m_MainValueTrueUnit == _T("\u00B0L")) data = 360 - m_MainValueTrue; else data = m_MainValueTrue; // The arrow should stay inside fixed limits if (data < m_MainValueMin) val = m_MainValueMin; else if (data > m_MainValueMax) val = m_MainValueMax; else val = data; value = deg2rad((val - m_MainValueMin) * m_AngleRange / (m_MainValueMax - m_MainValueMin)) + deg2rad(m_AngleStart - ANGLE_OFFSET); points[0].x = m_cx + (m_radius * 0.95 * cos(value - .010)); points[0].y = m_cy + (m_radius * 0.95 * sin(value - .010)); points[1].x = m_cx + (m_radius * 0.95 * cos(value + .015)); points[1].y = m_cy + (m_radius * 0.95 * sin(value + .015)); points[2].x = m_cx + (m_radius * 0.22 * cos(value + 2.8)); points[2].y = m_cy + (m_radius * 0.22 * sin(value + 2.8)); points[3].x = m_cx + (m_radius * 0.22 * cos(value - 2.8)); points[3].y = m_cy + (m_radius * 0.22 * sin(value - 2.8)); dc->DrawPolygon(4, points, 0, 0); /* Apparent Wind*/ dc->SetPen(*wxTRANSPARENT_PEN); GetGlobalColor(_T("DASHN"), &cl); wxBrush brush; brush.SetStyle(wxSOLID); brush.SetColour(cl); dc->SetBrush(brush); /* this is fix for a +/-180° round instrument, when m_MainValue is supplied as <0..180><L | R> * for example TWA & AWA */ if (m_MainValueAppUnit == _T("\u00B0L")) data = 360 - m_MainValueApp; else data = m_MainValueApp; // The arrow should stay inside fixed limits if (data < m_MainValueMin) val = m_MainValueMin; else if (data > m_MainValueMax) val = m_MainValueMax; else val = data; value = deg2rad((val - m_MainValueMin) * m_AngleRange / (m_MainValueMax - m_MainValueMin)) + deg2rad(m_AngleStart - ANGLE_OFFSET); points[0].x = m_cx + (m_radius * 0.95 * cos(value - .010)); points[0].y = m_cy + (m_radius * 0.95 * sin(value - .010)); points[1].x = m_cx + (m_radius * 0.95 * cos(value + .015)); points[1].y = m_cy + (m_radius * 0.95 * sin(value + .015)); points[2].x = m_cx + (m_radius * 0.22 * cos(value + 2.8)); points[2].y = m_cy + (m_radius * 0.22 * sin(value + 2.8)); points[3].x = m_cx + (m_radius * 0.22 * cos(value - 2.8)); points[3].y = m_cy + (m_radius * 0.22 * sin(value - 2.8)); dc->DrawPolygon(4, points, 0, 0); }
void osd_wp() { PangoContext *context = NULL; PangoLayout *layout = NULL; PangoFontDescription *desc = NULL; GdkColor color; GdkGC *gc; gchar *buffer; static gchar distunit[3]; static int width = 0, height = 0; float distance; double unit_conv = 1; printf("** %s(): \n",__PRETTY_FUNCTION__); if(gpsdata && mouse_dx == 0 && mouse_dy == 0) { switch (global_speed_unit) { case 0: unit_conv = 1.0; g_sprintf(distunit, "%s", "km"); break; case 1 : unit_conv = 1.0 / 1.609344; g_sprintf(distunit, "%s", "m"); break; case 2 : unit_conv = 1.0 / 1.852; g_sprintf(distunit, "%s", "NM"); break; } distance = get_distance(deg2rad(gpsdata->fix.latitude), deg2rad(gpsdata->fix.longitude), global_wp.lat,global_wp.lon); buffer = g_strdup_printf("%.3f\n%.1f°", distance*unit_conv, rad2deg(gpsdata->fix.bearing)); context = gtk_widget_get_pango_context (map_drawable); layout = pango_layout_new (context); desc = pango_font_description_new(); pango_font_description_set_size (desc, 12 * PANGO_SCALE); pango_layout_set_font_description (layout, desc); pango_layout_set_text (layout, buffer, strlen(buffer)); gc = gdk_gc_new (map_drawable->window); color.red = 0; color.green = 0; color.blue = 0; gdk_gc_set_rgb_fg_color (gc, &color); gdk_draw_drawable ( map_drawable->window, map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)], pixmap, global_drawingarea_width - width - 10, global_drawingarea_height - height - 10, global_drawingarea_width - width - 10, global_drawingarea_height - height - 10, width+10,height+10); pango_layout_get_pixel_size(layout, &width, &height); gdk_draw_layout(map_drawable->window, gc, global_drawingarea_width - width - 10, global_drawingarea_height - height -10, layout); g_free(buffer); pango_font_description_free (desc); g_object_unref (layout); g_object_unref (gc); } }
void CWallmarksEngine::AddWallmark_internal (CDB::TRI* pTri, const Fvector* pVerts, const Fvector &contact_point, ref_shader hShader, float sz) { // query for polygons in bounding box // calculate adjacency { Fbox bb_query; Fvector bbc,bbd; bb_query.set (contact_point,contact_point); bb_query.grow (sz*2.5f); bb_query.get_CD (bbc,bbd); xrc.box_options (CDB::OPT_FULL_TEST); xrc.box_query (g_pGameLevel->ObjectSpace.GetStaticModel(),bbc,bbd); u32 triCount = xrc.r_count (); if (0==triCount) return; CDB::TRI* tris = g_pGameLevel->ObjectSpace.GetStaticTris(); sml_collector.clear (); sml_collector.add_face_packed_D (pVerts[pTri->verts[0]],pVerts[pTri->verts[1]],pVerts[pTri->verts[2]],0); for (u32 t=0; t<triCount; t++) { CDB::TRI* T = tris+xrc.r_begin()[t].id; if (T==pTri) continue; sml_collector.add_face_packed_D (pVerts[T->verts[0]],pVerts[T->verts[1]],pVerts[T->verts[2]],0); } sml_collector.calc_adjacency (sml_adjacency); } // calc face normal Fvector N; N.mknormal (pVerts[pTri->verts[0]],pVerts[pTri->verts[1]],pVerts[pTri->verts[2]]); sml_normal.set (N); // build 3D ortho-frustum Fmatrix mView,mRot; BuildMatrix (mView,1/sz,contact_point); mRot.rotateZ (::Random.randF(deg2rad(-20.f),deg2rad(20.f))); mView.mulA_43 (mRot); sml_clipper.CreateFromMatrix (mView,FRUSTUM_P_LRTB); // create wallmark static_wallmark* W = static_wm_allocate(); RecurseTri (0,mView,*W); // calc sphere if (W->verts.size()<3) { static_wm_destroy(W); return; } else { Fbox bb; bb.invalidate(); FVF::LIT* I=&*W->verts.begin (); FVF::LIT* E=&*W->verts.end (); for (; I!=E; I++) bb.modify (I->p); bb.getsphere (W->bounds.P,W->bounds.R); } if (W->bounds.R < 1.f) { // search if similar wallmark exists wm_slot* slot = FindSlot (hShader); if (slot){ StaticWMVecIt it = slot->static_items.begin (); StaticWMVecIt end = slot->static_items.end (); for (; it!=end; it++) { static_wallmark* wm = *it; if (wm->bounds.P.similar(W->bounds.P,0.02f)){ // replace static_wm_destroy (wm); *it = W; return; } } } else { slot = AppendSlot(hShader); } // no similar - register _new_ slot->static_items.push_back(W); } }
FBOViewportPtr createSceneFBO(void) { //Create Camera Beacon Matrix CameraMat; CameraMat.setTranslate(0.0f,0.0f,4.0f); TransformPtr CameraBeconCore = Transform::create(); beginEditCP(CameraBeconCore, Transform::MatrixFieldMask); CameraBeconCore->setMatrix(CameraMat); endEditCP(CameraBeconCore, Transform::MatrixFieldMask); NodePtr CameraBeconNode = Node::create(); beginEditCP(CameraBeconNode, Node::CoreFieldMask); CameraBeconNode->setCore(CameraBeconCore); endEditCP(CameraBeconNode, Node::CoreFieldMask); //Create Camera PerspectiveCameraPtr TheCamera = PerspectiveCamera::create(); beginEditCP(TheCamera); TheCamera->setFov(deg2rad(60.0f)); TheCamera->setAspect(1.0f); TheCamera->setNear(0.1f); TheCamera->setFar(100.0f); TheCamera->setBeacon(CameraBeconNode); endEditCP(TheCamera); //Make the Material BlinnMaterialPtr TheMaterial = BlinnMaterial::create(); beginEditCP(TheMaterial); TheMaterial->setDiffuse(0.8); TheMaterial->setColor(Color3f(1.0,1.0,1.0)); TheMaterial->setAmbientColor(Color3f(1.0,1.0,1.0)); TheMaterial->setNumLights(1); endEditCP(TheMaterial); // Make Torus Node (creates Torus in background of scene) NodePtr TorusGeometryNode = makeTorus(.5, 2, 24, 48); beginEditCP(TorusGeometryNode->getCore()); GeometryPtr::dcast(TorusGeometryNode->getCore())->setMaterial(TheMaterial); endEditCP(TorusGeometryNode->getCore()); calcVertexNormals(GeometryPtr::dcast(TorusGeometryNode->getCore())); calcVertexTangents(GeometryPtr::dcast(TorusGeometryNode->getCore()),0,Geometry::TexCoords7FieldId, Geometry::TexCoords6FieldId); RootTransformCore = Transform::create(); NodePtr TorusTransformNode = Node::create(); beginEditCP(TorusTransformNode, Node::CoreFieldMask); TorusTransformNode->setCore(RootTransformCore); TorusTransformNode->addChild(TorusGeometryNode); endEditCP(TorusTransformNode, Node::CoreFieldMask); //Create Light Beacon Matrix LightMat; LightMat.setTranslate(0.0f,10.0f,1.0f); TransformPtr LightBeconCore = Transform::create(); beginEditCP(LightBeconCore, Transform::MatrixFieldMask); LightBeconCore->setMatrix(LightMat); endEditCP(LightBeconCore, Transform::MatrixFieldMask); NodePtr LightBeconNode = Node::create(); beginEditCP(LightBeconNode, Node::CoreFieldMask); LightBeconNode->setCore(LightBeconCore); endEditCP(LightBeconNode, Node::CoreFieldMask); //Create Light TheLight = PointLight::create(); beginEditCP(TheLight); TheLight->setBeacon(LightBeconNode); endEditCP(TheLight); NodePtr LightNode = Node::create(); beginEditCP(LightNode, Node::CoreFieldMask); LightNode->setCore(TheLight); LightNode->addChild(TorusTransformNode); endEditCP(LightNode, Node::CoreFieldMask); //Create Root NodePtr TheRoot = Node::create(); beginEditCP(TheRoot); TheRoot->setCore(Group::create()); TheRoot->addChild(CameraBeconNode); TheRoot->addChild(LightNode); TheRoot->addChild(LightBeconNode); endEditCP(TheRoot); //Create Background SolidBackgroundPtr TheBackground = SolidBackground::create(); TheBackground->setColor(Color3f(1.0,0.0,0.0)); //DepthClearBackgroundPtr TheBackground = DepthClearBackground::create(); //Create the Image ImagePtr TheColorImage = Image::create(); TheColorImage->set(Image::OSG_RGB_PF,2,2,1,1,1,0.0f,0,Image::OSG_FLOAT16_IMAGEDATA); //Create the texture TextureChunkPtr TheColorTextureChunk = TextureChunk::create(); beginEditCP(TheColorTextureChunk); TheColorTextureChunk->setImage(TheColorImage); TheColorTextureChunk->setMinFilter(GL_NEAREST); TheColorTextureChunk->setMagFilter(GL_NEAREST); TheColorTextureChunk->setWrapS(GL_CLAMP_TO_EDGE); TheColorTextureChunk->setWrapR(GL_CLAMP_TO_EDGE); TheColorTextureChunk->setScale(false); TheColorTextureChunk->setNPOTMatrixScale(true); TheColorTextureChunk->setEnvMode(GL_REPLACE); TheColorTextureChunk->setInternalFormat(GL_RGB16F); endEditCP(TheColorTextureChunk); //Create FBO FBOViewportPtr TheFBO = FBOViewport::create(); beginEditCP(TheFBO); TheFBO->setBackground(TheBackground); TheFBO->setRoot(TheRoot); TheFBO->setCamera(TheCamera); TheFBO->setEnabled(true); TheFBO->getTextures().push_back(TheColorTextureChunk); TheFBO->setStorageWidth(TheColorTextureChunk->getImage()->getWidth()); TheFBO->setStorageHeight(TheColorTextureChunk->getImage()->getHeight()); TheFBO->setSize(0,0,TheColorTextureChunk->getImage()->getWidth()-1, TheColorTextureChunk->getImage()->getHeight()-1); endEditCP(TheFBO); return TheFBO; }
int main(int argc, char** args) { char* outfn = NULL; int c; int startoptind; int nrecords, nobs, nfiles; int Nside = 8; usnob_fits** usnobs; int i, HP; int slicecounts[180]; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case '?': case 'h': print_help(args[0]); exit(0); case 'N': Nside = atoi(optarg); break; case 'o': outfn = optarg; break; } } if (!outfn || (optind == argc)) { print_help(args[0]); exit(-1); } if (Nside < 1) { fprintf(stderr, "Nside must be >= 1.\n"); print_help(args[0]); exit(-1); } HP = 12 * Nside * Nside; printf("Nside = %i, using %i healpixes.\n", Nside, HP); { struct rlimit lim; getrlimit(RLIMIT_NOFILE, &lim); printf("Maximum number of files that can be opened: %li soft, %li hard\n", (long int)lim.rlim_cur, (long int)lim.rlim_max); if (lim.rlim_cur < HP) { printf("\n\nWARNING: This process is likely to fail - probably after working for many hours!\n\n\n"); sleep(5); } } usnobs = calloc(HP, sizeof(usnob_fits*)); memset(slicecounts, 0, 180 * sizeof(uint)); nrecords = 0; nobs = 0; nfiles = 0; printf("Reading USNO files... "); fflush(stdout); startoptind = optind; for (; optind<argc; optind++) { char* infn; FILE* fid; unsigned char* map; size_t map_size; int i; int lastgrass; infn = args[optind]; fid = fopen(infn, "rb"); if (!fid) { fprintf(stderr, "Couldn't open input file %s: %s\n", infn, strerror(errno)); exit(-1); } printf("Reading file %i of %i: %s\n", optind - startoptind, argc - startoptind, infn); if (fseeko(fid, 0, SEEK_END)) { fprintf(stderr, "Couldn't seek to end of input file %s: %s\n", infn, strerror(errno)); exit(-1); } map_size = ftello(fid); fseeko(fid, 0, SEEK_SET); map = mmap(NULL, map_size, PROT_READ, MAP_SHARED, fileno(fid), 0); if (map == MAP_FAILED) { fprintf(stderr, "Couldn't mmap input file %s: %s\n", infn, strerror(errno)); exit(-1); } fclose(fid); if (map_size % USNOB_RECORD_SIZE) { fprintf(stderr, "Warning, input file %s has size %u which is not divisible into %i-byte records.\n", infn, (unsigned int)map_size, USNOB_RECORD_SIZE); } lastgrass = 0; for (i=0; i<map_size; i+=USNOB_RECORD_SIZE) { usnob_entry entry; int hp; int slice; if ((i * 80 / map_size) != lastgrass) { printf("."); fflush(stdout); lastgrass = i * 80 / map_size; } if (usnob_parse_entry(map + i, &entry)) { fprintf(stderr, "Failed to parse USNOB entry: offset %i in file %s.\n", i, infn); exit(-1); } // compute the usnob_id based on its DEC slice and index. slice = (int)(entry.dec + 90.0); assert(slice < 180); assert((slicecounts[slice] & 0xff000000) == 0); entry.usnob_id = (slice << 24) | (slicecounts[slice]); slicecounts[slice]++; hp = radectohealpix(deg2rad(entry.ra), deg2rad(entry.dec), Nside); if (!usnobs[hp]) { char fn[256]; qfits_header* hdr; sprintf(fn, outfn, hp); usnobs[hp] = usnob_fits_open_for_writing(fn); if (!usnobs[hp]) { fprintf(stderr, "Failed to initialized FITS file %i (filename %s).\n", hp, fn); exit(-1); } if (usnob_fits_remove_an_diffraction_spike_column(usnobs[hp])) { fprintf(stderr, "Failed to remove the AN_DIFFRACTION_SPIKE column.\n"); exit(-1); } hdr = usnob_fits_get_header(usnobs[hp]); assert(hdr); // header remarks... fits_header_add_int(hdr, "HEALPIX", hp, "The healpix number of this catalog."); fits_header_add_int(hdr, "NSIDE", Nside, "The healpix resolution."); BOILERPLATE_ADD_FITS_HEADERS(hdr); qfits_header_add(hdr, "HISTORY", "Created by the program \"usnobtofits\"", NULL, NULL); qfits_header_add(hdr, "HISTORY", "usnobtofits command line:", NULL, NULL); fits_add_args(hdr, args, argc); qfits_header_add(hdr, "HISTORY", "(end of command line)", NULL, NULL); if (usnob_fits_write_headers(usnobs[hp])) { fprintf(stderr, "Failed to write header for FITS file %s.\n", fn); exit(-1); } } if (usnob_fits_write_entry(usnobs[hp], &entry)) { fprintf(stderr, "Failed to write FITS entry.\n"); exit(-1); } nrecords++; nobs += (entry.ndetections == 0 ? 1 : entry.ndetections); } munmap(map, map_size); nfiles++; printf("\n"); } // close all the files... for (i=0; i<HP; i++) { if (!usnobs[i]) continue; if (usnob_fits_fix_headers(usnobs[i]) || usnob_fits_close(usnobs[i])) { fprintf(stderr, "Failed to close file %i: %s\n", i, strerror(errno)); } } printf("Read %u files, %u records, %u observations.\n", nfiles, nrecords, nobs); free(usnobs); return 0; }
// Convert to actual length double degp2meter(double degp, double latp) { return RadiusMeter * deg2rad(degp) * cos(deg2rad(latp2lat(latp))); }
void paint_pois() { int pixel_x, pixel_y, x, y; float lat, lon; GSList *list; GdkColor color; GError *error = NULL; static GdkPixbuf *photo_icon = NULL; static GdkGC *gc; printf("*** %s(): \n",__PRETTY_FUNCTION__); if (!gc) gc = gdk_gc_new(pixmap); color.green = 0; color.blue = 60000; color.red = 0; gdk_gc_set_rgb_fg_color(gc, &color); if(!photo_icon) { photo_icon = gdk_pixbuf_new_from_file_at_size ( PACKAGE_PIXMAPS_DIR "/tangogps-poi.png", 25,25, &error); } if(global_show_pois) { get_pois(); for(list = poi_list; list != NULL; list = list->next) { poi_t *p = list->data; lat = deg2rad(p->lat_deg); lon = deg2rad(p->lon_deg); pixel_x = lon2pixel(global_zoom, lon); pixel_y = lat2pixel(global_zoom, lat); x = pixel_x - global_x; y = pixel_y - global_y; p->screen_x = x; p->screen_y = y; if(!photo_icon) { gdk_draw_arc ( pixmap, gc, TRUE, x-4, y-4, 8,8, 0,23040); } else { gdk_draw_pixbuf ( pixmap, NULL, photo_icon, 0,0, x-12,y-12, 24,24, GDK_RGB_DITHER_NONE, 0, 0); } gtk_widget_queue_draw_area ( map_drawable, x-12, y-12, 24,24); printf("POI: %s lat %f - lon %f\n",p->keywords,p->lat_deg, p->lon_deg); } } }
double meter2degp(double meter, double latp) { return rad2deg((1/RadiusMeter) * (meter / cos(deg2rad(latp2lat(latp))))); }
void show_poi_detail() { GtkWidget *window, *widget; GtkWidget *label; GSList *list; gchar *buffer = NULL, *buffer2 = NULL; gboolean poi_found = FALSE; float lat, lon,lat_deg,lon_deg; float distance=0; waypoint_t *wp = g_new0(waypoint_t, 1); poi_t *p, *this_poi = NULL; window = create_window5(); printf("screen x,y: %d %d \n",mouse_x, mouse_y); lat = pixel2lat(global_zoom, global_y+mouse_y); lon = pixel2lon(global_zoom, global_x+mouse_x); lat_deg = rad2deg(lat); lon_deg = rad2deg(lon); printf ("##### Lonitude: %f %f - %f %f \n", lat, lon, lat_deg, lon_deg); if(gpsdata !=NULL && !global_myposition.lat && !global_myposition.lon) { distance = 6371.0 * acos(sin(deg2rad(gpsdata->fix.latitude)) * sin(lat) + cos(deg2rad(gpsdata->fix.latitude)) * cos(lat) * cos(lon - deg2rad(gpsdata->fix.longitude)) ); } else if(global_myposition.lat && global_myposition.lon) { distance = 6371.0 * acos(sin(deg2rad(global_myposition.lat)) * sin(lat) + cos(deg2rad(global_myposition.lat)) * cos(lat) * cos(lon - deg2rad(global_myposition.lon)) ); } printf("*** %s(): \n",__PRETTY_FUNCTION__); label = lookup_widget(window,"label110"); for(list = poi_list; list != NULL; list = list->next) { p = list->data; printf("\n\nPIXEL POI: %d %d \n\n",p->screen_x,p->screen_y); if(abs(p->screen_x - mouse_x) < 12 && abs(p->screen_y - mouse_y) < 12 ) { printf("FOUND POI X: %d %d %s\n",p->screen_x, mouse_x, my_strescape_back(p->keywords,NULL)); buffer = g_strdup_printf( "<b>%s</b> ", my_strescape_back(p->keywords,NULL)); buffer2 = g_strdup_printf("%s \n\nDistance: %.3fkm ", my_strescape_back(p->desc,NULL), distance); printf("%s %s \n",buffer, buffer2); poi_found = TRUE; wp->lat = deg2rad(p->lat_deg); wp->lon = deg2rad(p->lon_deg); this_poi = list->data; } } if(!poi_found) g_sprintf(buffer, "<b>No POI found</b>\n"); gtk_label_set_label(GTK_LABEL(label),buffer); label = lookup_widget(window,"label111"); gtk_label_set_label(GTK_LABEL(label), buffer2); widget = lookup_widget(window, "button27"); g_signal_connect ( (gpointer) widget, "clicked", G_CALLBACK (on_button27_clicked), (gpointer) wp); if (this_poi != NULL) { this_poi->widget = window; widget = lookup_widget(window, "button33"); g_signal_connect ( (gpointer) widget, "clicked", G_CALLBACK (on_button33_clicked), (gpointer) this_poi); widget = lookup_widget(window, "button34"); g_signal_connect ( (gpointer) widget, "clicked", G_CALLBACK (on_button34_clicked), (gpointer) this_poi); } gtk_widget_show(window); }
AffineTransform& AffineTransform::skewX(double angle) { return shear(tan(deg2rad(angle)), 0); }
AffineTransform& AffineTransform::rotate(double a) { // angle is in degree. Switch to radian return rotateRadians(deg2rad(a)); }
void dbg_draw_frustum (float FOV, float _FAR, float A, Fvector &P, Fvector &D, Fvector &U) { //if (!bDebug) return; float YFov = deg2rad(FOV*A); float XFov = deg2rad(FOV); // calc window extents in camera coords float wR=tanf(XFov*0.5f); float wL=-wR; float wT=tanf(YFov*0.5f); float wB=-wT; // calc x-axis (viewhoriz) and store cop // here we are assuring that vectors are perpendicular & normalized Fvector R,COP; D.normalize (); R.crossproduct (D,U); R.normalize (); U.crossproduct (R,D); U.normalize (); COP.set (P); // calculate the corner vertices of the window Fvector sPts[4]; // silhouette points (corners of window) Fvector Offset,T; Offset.add (D,COP); sPts[0].mul(R,wR); T.mad(Offset,U,wT); sPts[0].add(T); sPts[1].mul(R,wL); T.mad(Offset,U,wT); sPts[1].add(T); sPts[2].mul(R,wL); T.mad(Offset,U,wB); sPts[2].add(T); sPts[3].mul(R,wR); T.mad(Offset,U,wB); sPts[3].add(T); // find projector direction vectors (from cop through silhouette pts) Fvector ProjDirs[4]; ProjDirs[0].sub(sPts[0],COP); ProjDirs[1].sub(sPts[1],COP); ProjDirs[2].sub(sPts[2],COP); ProjDirs[3].sub(sPts[3],COP); //RCache.set_CullMode (CULL_NONE); DRender->CacheSetCullMode(IDebugRender::cmNONE); //CHK_DX(HW.pDevice->SetRenderState (D3DRS_AMBIENT, 0xffffffff )); DRender->SetAmbient(0xffffffff); Fvector _F[4]; _F[0].mad(COP, ProjDirs[0], _FAR); _F[1].mad(COP, ProjDirs[1], _FAR); _F[2].mad(COP, ProjDirs[2], _FAR); _F[3].mad(COP, ProjDirs[3], _FAR); // u32 CT = color_rgba(255,255,255,64); u32 CL = color_rgba(0,255,255,255); Fmatrix& M = Fidentity; //ref_shader l_tShaderReference = Level().ObjectSpace.dbgGetShader(); //RCache.set_Shader (l_tShaderReference); Level().ObjectSpace.m_pRender->SetShader(); // RCache.dbg_DrawTRI (M,COP,_F[0],_F[1],CT); // RCache.dbg_DrawTRI (M,COP,_F[1],_F[2],CT); // RCache.dbg_DrawTRI (M,COP,_F[2],_F[3],CT); // RCache.dbg_DrawTRI (M,COP,_F[3],_F[0],CT); Level().debug_renderer().draw_line (M,COP,_F[0],CL); Level().debug_renderer().draw_line (M,COP,_F[1],CL); Level().debug_renderer().draw_line (M,COP,_F[2],CL); Level().debug_renderer().draw_line (M,COP,_F[3],CL); Level().debug_renderer().draw_line (M,_F[0],_F[1],CL); Level().debug_renderer().draw_line (M,_F[1],_F[2],CL); Level().debug_renderer().draw_line (M,_F[2],_F[3],CL); Level().debug_renderer().draw_line (M,_F[3],_F[0],CL); //RCache.set_CullMode (CULL_CCW); DRender->CacheSetCullMode(IDebugRender::cmCCW); //CHK_DX(HW.pDevice->SetRenderState (D3DRS_AMBIENT, 0 )); DRender->SetAmbient(0); }
static double ptarray_area_spheroid(const POINTARRAY *pa, const SPHEROID *spheroid) { GEOGRAPHIC_POINT a, b; POINT2D p; int i; double area = 0.0; GBOX gbox2d; int in_south = LW_FALSE; double delta_lon_tolerance; double latitude_min; gbox2d.flags = gflags(0, 0, 0); /* Return zero on non-sensical inputs */ if ( ! pa || pa->npoints < 4 ) return 0.0; /* Get the raw min/max values for the latitudes */ ptarray_calculate_gbox(pa, &gbox2d); if ( signum(gbox2d.ymin) != signum(gbox2d.ymax) ) lwerror("ptarray_area_spheroid: cannot handle ptarray that crosses equator"); /* Geodetic bbox < 0.0 implies geometry is entirely in southern hemisphere */ if ( gbox2d.ymax < 0.0 ) in_south = LW_TRUE; LWDEBUGF(4, "gbox2d.ymax %.12g", gbox2d.ymax); /* Tolerance for strip area calculation */ if ( in_south ) { delta_lon_tolerance = (90.0 / (fabs(gbox2d.ymin) / 8.0) - 2.0) / 10000.0; latitude_min = deg2rad(fabs(gbox2d.ymax)); } else { delta_lon_tolerance = (90.0 / (fabs(gbox2d.ymax) / 8.0) - 2.0) / 10000.0; latitude_min = deg2rad(gbox2d.ymin); } /* Initialize first point */ getPoint2d_p(pa, 0, &p); geographic_point_init(p.x, p.y, &a); for ( i = 1; i < pa->npoints; i++ ) { GEOGRAPHIC_POINT a1, b1; double strip_area = 0.0; double delta_lon = 0.0; LWDEBUGF(4, "edge #%d", i); getPoint2d_p(pa, i, &p); geographic_point_init(p.x, p.y, &b); a1 = a; b1 = b; /* Flip into north if in south */ if ( in_south ) { a1.lat = -1.0 * a1.lat; b1.lat = -1.0 * b1.lat; } LWDEBUGF(4, "in_south %d", in_south); LWDEBUGF(4, "crosses_dateline(a, b) %d", crosses_dateline(&a, &b) ); if ( crosses_dateline(&a, &b) ) { double shift; if ( a1.lon > 0.0 ) shift = (M_PI - a1.lon) + 0.088; /* About 5deg more */ else shift = (M_PI - b1.lon) + 0.088; /* About 5deg more */ LWDEBUGF(4, "shift: %.8g", shift); LWDEBUGF(4, "before shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon); point_shift(&a1, shift); point_shift(&b1, shift); LWDEBUGF(4, "after shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon); } delta_lon = fabs(b1.lon - a1.lon); LWDEBUGF(4, "a1(%.18g %.18g) b1(%.18g %.18g)", a1.lat, a1.lon, b1.lat, b1.lon); LWDEBUGF(4, "delta_lon %.18g", delta_lon); LWDEBUGF(4, "delta_lon_tolerance %.18g", delta_lon_tolerance); if ( delta_lon > 0.0 ) { if ( delta_lon < delta_lon_tolerance ) { strip_area = spheroid_striparea(&a1, &b1, latitude_min, spheroid); LWDEBUGF(4, "strip_area %.12g", strip_area); area += strip_area; } else { GEOGRAPHIC_POINT p, q; double step = floor(delta_lon / delta_lon_tolerance); double distance = spheroid_distance(&a1, &b1, spheroid); double pDistance = 0.0; int j = 0; LWDEBUGF(4, "step %.18g", step); LWDEBUGF(4, "distance %.18g", distance); step = distance / step; LWDEBUGF(4, "step %.18g", step); p = a1; while (pDistance < (distance - step * 1.01)) { double azimuth = spheroid_direction(&p, &b1, spheroid); j++; LWDEBUGF(4, " iteration %d", j); LWDEBUGF(4, " azimuth %.12g", azimuth); pDistance = pDistance + step; LWDEBUGF(4, " pDistance %.12g", pDistance); spheroid_project(&p, spheroid, step, azimuth, &q); strip_area = spheroid_striparea(&p, &q, latitude_min, spheroid); LWDEBUGF(4, " strip_area %.12g", strip_area); area += strip_area; LWDEBUGF(4, " area %.12g", area); p.lat = q.lat; p.lon = q.lon; } strip_area = spheroid_striparea(&p, &b1, latitude_min, spheroid); area += strip_area; } } /* B gets incremented in the next loop, so we save the value here */ a = b; } return fabs(area); }
/* Law of cosines; ________________________ / 2 2 VW = / VA + VB - 2 VA VB cos(A) \/ */ double Polar::VelocityTrueWind2(double VA, double VB, double A) { return sqrt(VA*VA + VB*VB - 2*VA*VB*cos(deg2rad(A))); }
static qreal zoom2resolution(int zoom, qreal y) { return (WGS84_RADIUS * 2 * M_PI / Tile::size() * cos(2 * atan(exp(deg2rad(y))) - M_PI/2)) / pow(2.0, zoom); }
/* Purpose: calculate the equation of center for the sun (degrees) */ double calcSunEqOfCenter(double t) { double m = deg2rad(calcGeomMeanAnomalySun(t)); return sin(m) * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin(m+m) * (0.019993 - 0.000101 * t) + sin(m+m+m) * 0.000289; }
// Project latitude (spherical Mercator) // (if calling with raw coords, remember to divide/multiply by 10000000.0) double lat2latp(double lat) { return rad2deg(log(tan(deg2rad(lat+90.0)/2.0))); }
/* Purpose: calculate the corrected obliquity of the ecliptic (degrees) */ double calcObliquityCorrection(double t) { return calcMeanObliquityOfEcliptic(t) + 0.00256*cos(deg2rad(125.04-1934.136*t)); }
double latp2lat(double latp) { return rad2deg(atan(exp(deg2rad(latp)))*2.0)-90.0; }
void paint_pois() { int pixel_x, pixel_y, x, y; float lat, lon; GSList *list; GdkColor color; static GdkGC *gc; if (!gc) gc = gdk_gc_new(pixmap); color.green = 0; color.blue = 60000; color.red = 0; gdk_gc_set_rgb_fg_color(gc, &color); if(global_show_pois) { get_pois(); for(list = poi_list; list != NULL; list = list->next) { poi_t *p = list->data; GdkPixbuf *photo_icon = get_poi_icon (p); int icon_width = gdk_pixbuf_get_width (photo_icon); int icon_height = gdk_pixbuf_get_width (photo_icon); lat = deg2rad(p->lat_deg); lon = deg2rad(p->lon_deg); pixel_x = lon2pixel(global_zoom, lon); pixel_y = lat2pixel(global_zoom, lat); x = pixel_x - global_x; y = pixel_y - global_y; p->screen_x = x; p->screen_y = y; if(!photo_icon) { gdk_draw_arc ( pixmap, gc, TRUE, x-4, y-4, 8,8, 0,23040); } else { gdk_draw_pixbuf ( pixmap, NULL, photo_icon, 0,0, x - icon_width/2, y - icon_height/2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); } gtk_widget_queue_draw_area ( map_drawable, x - icon_width/2, y - icon_height/2, icon_width, icon_height); } } }
void BoatDialog::OnPaintPlot(wxPaintEvent& event) { wxWindow *window = dynamic_cast<wxWindow*>(event.GetEventObject()); if(!window) return; wxPaintDC dc(window); dc.SetBackgroundMode(wxTRANSPARENT); long index = SelectedPolar(); if(index < 0) { dc.SetTextForeground(*wxBLACK); wxString str = _("Select a polar to view plot"); int sw, sh; dc.GetTextExtent(str, &sw, &sh); dc.DrawText(str, 0, 0); return; } int plottype = m_cPlotType->GetSelection(); int w, h; m_PlotWindow->GetSize( &w, &h); double maxVB = 0; Polar &polar = m_Boat.Polars[index]; /* plot scale */ int selection = m_cPlotVariable->GetSelection(); for(unsigned int VWi = 0; VWi<polar.wind_speeds.size(); VWi++) { double windspeed = polar.wind_speeds[VWi].VW; for(unsigned int Wi = 0; Wi<polar.degree_steps.size(); Wi++) { double W = polar.degree_steps[Wi]; double VB; if(selection < 2) VB = polar.Speed(W, windspeed); else VB = polar.SpeedAtApparentWindSpeed(W, windspeed); if(VB > maxVB) maxVB = VB; } } dc.SetPen(wxPen(wxColor(0, 0, 0))); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetTextForeground(wxColour(0, 55, 75)); if(maxVB <= 0) maxVB = 1; /* avoid lock */ double Vstep = ceil(maxVB / 5); maxVB += Vstep; m_PlotScale = (w < h ? w : h)/1.8 / (maxVB+1); // m_PlotScale = h/1.8 / (maxVB+1); bool full = m_cbFullPlot->GetValue(); int xc = full ? w / 2 : 0; if(plottype == 0) { /* polar circles */ for(double V = Vstep; V <= maxVB; V+=Vstep) { dc.DrawCircle(xc, h/2, V*m_PlotScale); dc.DrawText(wxString::Format(_T("%.0f"), V), xc, h/2+(int)V*m_PlotScale); } } else { for(double V = Vstep; V <= maxVB; V+=Vstep) { int y = h - 2*V*m_PlotScale; dc.DrawLine(0, y, w, y); dc.DrawText(wxString::Format(_T("%.0f"), V), 0, y); } } dc.SetTextForeground(wxColour(0, 0, 155)); if(plottype == 0) { /* polar meridians */ for(double B = 0; B < DEGREES; B+=15) { double x = maxVB*m_PlotScale*sin(deg2rad(B)); double y = maxVB*m_PlotScale*cos(deg2rad(B)); if(B < 180) dc.DrawLine(xc - x, h/2 + y, xc + x, h/2 - y); wxString str = wxString::Format(_T("%.0f"), B); int sw, sh; dc.GetTextExtent(str, &sw, &sh); dc.DrawText(str, xc + .9*x - sw/2, h/2 - .9*y - sh/2); } } else { for(int s = 0; s<num_wind_speeds; s++) { double windspeed = wind_speeds[s]; double x = s * w / num_wind_speeds; dc.DrawLine(x, 0, x, h); wxString str = wxString::Format(_T("%.0f"), windspeed); int sw, sh; dc.GetTextExtent(str, &sw, &sh); dc.DrawText(str, x, 0); } } int cx = (full ? w/2 : 0), cy = h/2; dc.SetPen(wxPen(wxColor(255, 0, 0), 2)); /* boat speeds */ if(plottype == 0) { for(unsigned int VWi = 0; VWi<polar.wind_speeds.size(); VWi++) { double VW, VA; switch(selection) { case 0: case 1: VW = polar.wind_speeds[VWi].VW; break; // use grid vw for va steps case 2: case 3: VA = polar.wind_speeds[VWi].VW; break; } bool lastvalid = false; int lx, ly; // for(unsigned int Wi = 0; Wi<polar.degree_steps.size()+full; Wi++) { // double W = polar.degree_steps[Wi%polar.degree_steps.size()]; double W0 = polar.degree_steps[0]; double Wn = polar.degree_steps[polar.degree_steps.size()-1]; double Wd = Wn - W0, Ws = Wd / floor(Wd); for(double W = W0; W <= Wn; W+= Ws) { double VB; switch(selection) { case 0: case 1: VB = polar.Speed(W, VW); break; case 2: case 3: VB = polar.SpeedAtApparentWindSpeed(W, VA); VW = Polar::VelocityTrueWind(VA, VB, W); break; } double a; switch(selection) { case 0: case 2: a = W; break; case 1: case 3: a = Polar::DirectionApparentWind(VB, W, VW); break; } int px, py; px = m_PlotScale*VB*sin(deg2rad(a)) + cx; py = -m_PlotScale*VB*cos(deg2rad(a)) + cy; if(lastvalid) { dc.DrawLine(lx, ly, px, py); if(full) dc.DrawLine(2*cx-lx, ly, 2*cx-px, py); // dc.DrawArc(lx, ly, px, py, cx, cy); } lx = px, ly = py; lastvalid = true; } } } else { for(unsigned int Wi = 0; Wi<polar.degree_steps.size(); Wi++) { double W = polar.degree_steps[Wi], VB; bool lastvalid = false; int lx, ly; for(unsigned int VWi = 0; VWi<polar.wind_speeds.size(); VWi++) { double windspeed = polar.wind_speeds[VWi].VW; double VW, VA; switch(selection) { case 0: case 1: VW = windspeed; break; // use grid vw for va steps case 2: case 3: VA = windspeed; break; } switch(selection) { case 0: case 1: VB = polar.Speed(W, VW); break; case 2: case 3: VB = polar.SpeedAtApparentWindSpeed(W, VA); VW = Polar::VelocityTrueWind(VA, VB, W); break; } #if 0 double a; switch(selection) { case 0: case 2: a = W; break; case 1: case 3: a = Polar::DirectionApparentWind(VB, W, VW); break; } #endif int px, py; int s; for(s = 0; s<num_wind_speeds-1; s++) { if(wind_speeds[s] > polar.wind_speeds[VWi].VW) break; } { // interpolate into non-linear windspeed space double x = windspeed, x1 = wind_speeds[s], x2 = wind_speeds[s+1]; double y1 = s * w / num_wind_speeds; double y2 = (s+1) * w / num_wind_speeds; px = x2 - x1 ? (y2 - y1)*(x - x1)/(x2 - x1) + y1 : y1; } py = h - 2*VB*m_PlotScale; if(lastvalid) { dc.DrawLine(lx, ly, px, py); if(full) dc.DrawLine(2*cx-lx, ly, 2*cx-px, py); } lx = px, ly = py; lastvalid = true; } } } /* vmg */ wxPoint lastp[4]; bool lastpvalid[4] = {false, false, false, false}; for(unsigned int VWi = 0; VWi<polar.wind_speeds.size(); VWi++) { double VW = polar.wind_speeds[VWi].VW; SailingVMG vmg = polar.GetVMGTrueWind(VW); for(int i=0; i<4; i++) { if(i%2 == 0 && !full) continue; if(i < 2) dc.SetPen(wxPen(wxColor(255, 0, 255), 2)); else dc.SetPen(wxPen(wxColor(255, 255, 0), 2)); double W = vmg.values[i]; if(isnan(W)) continue; double VB = polar.Speed(W, VW); double a; switch(selection) { case 0: case 2: a = W; break; case 1: case 3: a = Polar::DirectionApparentWind(VB, W, VW); break; } wxPoint p; if(plottype == 0) { p.x = m_PlotScale*VB*sin(deg2rad(a)) + cx; p.y = -m_PlotScale*VB*cos(deg2rad(a)) + cy; } else { p.x = a * w / (full ? 360 : 180) + cx; p.y = h - 2*VB*m_PlotScale; } if(lastpvalid[i]) dc.DrawLine(lastp[i], p); lastp[i] = p; lastpvalid[i] = true; } } }