void BExtractorDoc::FloodFillDIB(CDib *bm, CProgressDlg *prog) { int width = bm->GetWidth(); int height = bm->GetHeight(); byte target = 0x00; int result = 0; for (int i = 0; i < width; i++) { if ((i % 10) == 0) prog->SetPos(i * 200 / width); for (int j = 0; j < height; j++) { if (bm->GetPixel8(i,j) == target) { result = Fill(bm, i, j, 0x00, 0xff, width, height, 1); DPoint2 point; point.x = i_UTMx(i); point.y = i_UTMy(j); // rough heuristic: adjusts the coordinate more towards the //center of the original building point.x += 5; vtBuilding *bld = new vtBuilding; bld->SetRectangle(point, 10, 10); bld->SetStories(1); bld->GetLevel(1)->SetEdgeColor(RGBi(255,255,255)); // white roof m_Buildings.Append(bld); } } } }
bool SetupDefaultStructures(const vtString &fname) { if (fname != "") { if (g_DefaultStructures.ReadXML(fname)) return true; } // else supply some internal defaults and let the user know the load failed vtBuilding *pBld = g_DefaultStructures.NewBuilding(); vtLevel *pLevel; DPolygon2 DefaultFootprint; // Single edge DefaultFootprint.resize(1); DefaultFootprint[0].Append(DPoint2(0.0, 0.0)); DefaultFootprint[0].Append(DPoint2(0.0, 1.0)); // The default building is NOT a complete building // Alter the code here to set different hard coded // defaults for use in other operations // First set any structure tags needed // // NONE // // Now create the required number of levels // and set the values // // Level 0 pLevel = pBld->CreateLevel(DefaultFootprint); pLevel->m_iStories = 1; pLevel->m_fStoryHeight = 3.20f; pLevel->SetEdgeMaterial(BMAT_NAME_PLAIN); pLevel->SetEdgeColor(RGBi(255,0,0)); // Red pLevel->GetEdge(0)->m_iSlope = 90; // Level 1 pLevel = pBld->CreateLevel(DefaultFootprint); pLevel->m_iStories = 1; pLevel->m_fStoryHeight = 3.20f; pLevel->SetEdgeMaterial(BMAT_NAME_PLAIN); pLevel->SetEdgeColor(RGBi(255,240,225)); // Tan pLevel->GetEdge(0)->m_iSlope = 0; // Flat g_DefaultStructures.Append(pBld); return false; }
void Style::LoadFactoryDefaults() { const Default *d; for(d = &(Defaults[0]); d->h.v; d++) { Style *s = Get(d->h); FillDefaultStyle(s, d, /*factory=*/true); } SS.backgroundColor = RGBi(0, 0, 0); SS.bgImage.pixmap.Clear(); }
int vtStructureArray::AddFoundations(vtHeightField *pHF, bool progress_callback(int)) { vtLevel *pLev, *pNewLev; int i, j, pts, built = 0; float fElev; int selected = NumSelected(); int size = GetSize(); VTLOG("AddFoundations: %d selected, %d total, ", selected, size); for (i = 0; i < size; i++) { if (progress_callback != NULL) progress_callback(i * 99 / size); vtStructure *str = GetAt(i); vtBuilding *bld = str->GetBuilding(); if (!bld) continue; if (selected > 0 && !str->IsSelected()) continue; // Get the outer footprint of the lowest level pLev = bld->GetLevel(0); const DLine2 &foot = pLev->GetOuterFootprint(); pts = foot.GetSize(); float fMin = 1E9, fMax = -1E9; for (j = 0; j < pts; j++) { pHF->FindAltitudeOnEarth(foot.GetAt(j), fElev); if (fElev < fMin) fMin = fElev; if (fElev > fMax) fMax = fElev; } float fDiff = fMax - fMin; // if there's less than 50cm of depth, don't bother building // a foundation if (fDiff < 0.5f) continue; // Create and add a foundation level pNewLev = new vtLevel; pNewLev->m_iStories = 1; pNewLev->m_fStoryHeight = fDiff; bld->InsertLevel(0, pNewLev); bld->SetFootprint(0, foot); pNewLev->SetEdgeMaterial(BMAT_NAME_CEMENT); pNewLev->SetEdgeColor(RGBi(255, 255, 255)); built++; } VTLOG("%d added.\n", built); return built; }
//----------------------------------------------------------------------------- // If a color is almost white, then we can rewrite it to black, just so that // it won't disappear on file formats with a light background. //----------------------------------------------------------------------------- RgbColor Style::RewriteColor(RgbColor rgbin) { Vector rgb = Vector::From(rgbin.redF(), rgbin.greenF(), rgbin.blueF()); rgb = rgb.Minus(Vector::From(1, 1, 1)); if(rgb.Magnitude() < 0.4 && SS.fixExportColors) { // This is an almost-white color in a default style, which is // good for the default on-screen view (black bg) but probably // not desired in the exported files, which typically are shown // against white backgrounds. return RGBi(0, 0, 0); } else { return rgbin; } }
vtAbstractLayer *CreateNewAbstractPointLayer(vtTerrain *pTerr, bool bAskStyle) { // make a new abstract layer (points) vtFeatureSetPoint2D *pSet = new vtFeatureSetPoint2D; pSet->SetFilename("Untitled.shp"); pSet->AddField("Label", FT_String); // Inherit projection pSet->SetProjection(pTerr->GetProjection()); // Ask style for the new point layer vtTagArray props; props.SetValueBool("ObjectGeometry", false, true); props.SetValueBool("Labels", true, true); props.SetValueRGBi("LabelColor", RGBi(255,255,0), true); props.SetValueFloat("LabelHeight", 10.0f, true); props.SetValueInt("TextFieldIndex", 0, true); props.SetValueBool("LabelOutline", true, true); if (bAskStyle) { StyleDlg dlg(NULL, -1, _("Style")); dlg.SetFeatureSet(pSet); dlg.SetOptions(props); if (dlg.ShowModal() != wxID_OK) { delete pSet; return NULL; } dlg.GetOptions(props); } // wrap the features in an abstract layer vtAbstractLayer *ab_layer = new vtAbstractLayer; ab_layer->SetFeatureSet(pSet); ab_layer->AddProps(props); // add the new layer to the terrain pTerr->GetLayers().push_back(ab_layer); pTerr->SetActiveLayer(ab_layer); // Construct it once so it is set up for future visuals. pTerr->CreateAbstractLayerVisuals(ab_layer); // and show it in the layers dialog GetFrame()->m_pLayerDlg->RefreshTreeContents(); // full refresh return ab_layer; }
vtAbstractLayer *CreateNewAbstractLineLayer(vtTerrain *pTerr, bool bAskStyle) { // make a new abstract layer (points) vtFeatureSetLineString *pSet = new vtFeatureSetLineString; pSet->SetFilename("Untitled.shp"); pSet->AddField("Elevation", FT_Float); // Ask style for the new point layer vtTagArray props; props.SetValueBool("LineGeometry", true, true); props.SetValueRGBi("LineGeomColor", RGBi(255,255,0), true); props.SetValueFloat("LineGeomHeight", 10.0f, true); props.SetValueBool("Labels", false, true); if (bAskStyle) { StyleDlg dlg(NULL, -1, _("Style")); dlg.SetFeatureSet(pSet); dlg.SetOptions(props); // Show the "Line Geometry" page, which is most relevant for a line layer dlg.GetNotebook()->SetSelection(1); if (dlg.ShowModal() != wxID_OK) { delete pSet; return NULL; } dlg.GetOptions(props); } // wrap the features in an abstract layer vtAbstractLayer *ab_layer = new vtAbstractLayer(); ab_layer->SetFeatureSet(pSet); ab_layer->SetProps(props); // add the new layer to the terrain pTerr->GetLayers().push_back(ab_layer); pTerr->SetActiveLayer(ab_layer); // Construct it once so it is set up for future visuals. pTerr->CreateAbstractLayerVisuals(ab_layer); // and show it in the layers dialog GetFrame()->m_pLayerDlg->RefreshTreeContents(); // full refresh return ab_layer; }
void Style::LoadFactoryDefaults(void) { const Default *d; for(d = &(Defaults[0]); d->h.v; d++) { Style *s = Get(d->h); s->color = d->color; s->width = d->width; s->widthAs = UNITS_AS_PIXELS; s->textHeight = DEFAULT_TEXT_HEIGHT; s->textHeightAs = UNITS_AS_PIXELS; s->textOrigin = 0; s->textAngle = 0; s->visible = true; s->exportable = true; s->filled = false; s->fillColor = RGBf(0.3, 0.3, 0.3); s->name.strcpy(CnfPrefixToName(d->cnfPrefix)); } SS.backgroundColor = RGBi(0, 0, 0); if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile); SS.bgImage.fromFile = NULL; }
/** * Get the color of the building. In the case of multi-colored buildings, * note that this method returns only the first color encountered. * * \param which Can be either BLD_BASIC (color of the building) or BLD_ROOF * (color of the roof). */ RGBi vtBuilding::GetColor(BldColor which) const { int i, levs = m_Levels.GetSize(); for (i = 0; i < levs; i++) { vtLevel *pLev = m_Levels[i]; int j, edges = pLev->NumEdges(); for (j = 0; j < edges; j++) { vtEdge *edge = pLev->GetEdge(j); if (edge->m_iSlope < 90) { if (which == BLD_ROOF) return edge->m_Color; } else { if (which == BLD_BASIC) return edge->m_Color; } } } return RGBi(0,0,0); }
void SolveSpaceUI::Init() { SS.tangentArcRadius = 10.0; // Then, load the registry settings. int i; // Default list of colors for the model material modelColor[0] = CnfThawColor(RGBi(150, 150, 150), "ModelColor_0"); modelColor[1] = CnfThawColor(RGBi(100, 100, 100), "ModelColor_1"); modelColor[2] = CnfThawColor(RGBi( 30, 30, 30), "ModelColor_2"); modelColor[3] = CnfThawColor(RGBi(150, 0, 0), "ModelColor_3"); modelColor[4] = CnfThawColor(RGBi( 0, 100, 0), "ModelColor_4"); modelColor[5] = CnfThawColor(RGBi( 0, 80, 80), "ModelColor_5"); modelColor[6] = CnfThawColor(RGBi( 0, 0, 130), "ModelColor_6"); modelColor[7] = CnfThawColor(RGBi( 80, 0, 80), "ModelColor_7"); // Light intensities lightIntensity[0] = CnfThawFloat(1.0f, "LightIntensity_0"); lightIntensity[1] = CnfThawFloat(0.5f, "LightIntensity_1"); ambientIntensity = 0.3; // no setting for that yet // Light positions lightDir[0].x = CnfThawFloat(-1.0f, "LightDir_0_Right" ); lightDir[0].y = CnfThawFloat( 1.0f, "LightDir_0_Up" ); lightDir[0].z = CnfThawFloat( 0.0f, "LightDir_0_Forward" ); lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" ); lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" ); lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" ); exportMode = false; // Chord tolerance chordTol = CnfThawFloat(0.5f, "ChordTolerancePct"); // Max pwl segments to generate maxSegments = CnfThawInt(10, "MaxSegments"); // Chord tolerance exportChordTol = CnfThawFloat(0.1f, "ExportChordTolerance"); // Max pwl segments to generate exportMaxSegments = CnfThawInt(64, "ExportMaxSegments"); // View units viewUnits = (Unit)CnfThawInt((uint32_t)UNIT_MM, "ViewUnits"); // Number of digits after the decimal point afterDecimalMm = CnfThawInt(2, "AfterDecimalMm"); afterDecimalInch = CnfThawInt(3, "AfterDecimalInch"); // Camera tangent (determines perspective) cameraTangent = CnfThawFloat(0.3f/1e3f, "CameraTangent"); // Grid spacing gridSpacing = CnfThawFloat(5.0f, "GridSpacing"); // Export scale factor exportScale = CnfThawFloat(1.0f, "ExportScale"); // Export offset (cutter radius comp) exportOffset = CnfThawFloat(0.0f, "ExportOffset"); // Rewrite exported colors close to white into black (assuming white bg) fixExportColors = CnfThawBool(true, "FixExportColors"); // Draw back faces of triangles (when mesh is leaky/self-intersecting) drawBackFaces = CnfThawBool(true, "DrawBackFaces"); // Check that contours are closed and not self-intersecting checkClosedContour = CnfThawBool(true, "CheckClosedContour"); // Export shaded triangles in a 2d view exportShadedTriangles = CnfThawBool(true, "ExportShadedTriangles"); // Export pwl curves (instead of exact) always exportPwlCurves = CnfThawBool(false, "ExportPwlCurves"); // Background color on-screen backgroundColor = CnfThawColor(RGBi(0, 0, 0), "BackgroundColor"); // Whether export canvas size is fixed or derived from bbox exportCanvasSizeAuto = CnfThawBool(true, "ExportCanvasSizeAuto"); // Margins for automatic canvas size exportMargin.left = CnfThawFloat(5.0f, "ExportMargin_Left"); exportMargin.right = CnfThawFloat(5.0f, "ExportMargin_Right"); exportMargin.bottom = CnfThawFloat(5.0f, "ExportMargin_Bottom"); exportMargin.top = CnfThawFloat(5.0f, "ExportMargin_Top"); // Dimensions for fixed canvas size exportCanvas.width = CnfThawFloat(100.0f, "ExportCanvas_Width"); exportCanvas.height = CnfThawFloat(100.0f, "ExportCanvas_Height"); exportCanvas.dx = CnfThawFloat( 5.0f, "ExportCanvas_Dx"); exportCanvas.dy = CnfThawFloat( 5.0f, "ExportCanvas_Dy"); // Extra parameters when exporting G code gCode.depth = CnfThawFloat(10.0f, "GCode_Depth"); gCode.passes = CnfThawInt(1, "GCode_Passes"); gCode.feed = CnfThawFloat(10.0f, "GCode_Feed"); gCode.plungeFeed = CnfThawFloat(10.0f, "GCode_PlungeFeed"); // Show toolbar in the graphics window showToolbar = CnfThawBool(true, "ShowToolbar"); // Recent files menus for(i = 0; i < MAX_RECENT; i++) { RecentFile[i] = CnfThawString("", "RecentFile_" + std::to_string(i)); } RefreshRecentMenus(); // Autosave timer autosaveInterval = CnfThawInt(5, "AutosaveInterval"); // The default styles (colors, line widths, etc.) are also stored in the // configuration file, but we will automatically load those as we need // them. SetAutosaveTimerFor(autosaveInterval); NewFile(); AfterNewFile(); }
void vtElevLayer::RenderBitmap() { if (!m_pGrid) return; // flag as being rendered m_bNeedsDraw = false; // safety check if (m_ImageSize.x == 0 || m_ImageSize.y == 0) return; DetermineMeterSpacing(); clock_t tm1 = clock(); #if 0 // TODO: re-enable this friendly cancel behavior if (UpdateProgressDialog(j*100/m_ImageSize.y)) { wxString msg = _("Turn off displayed elevation for elevation layers?"); if (wxMessageBox(msg, _T(""), wxYES_NO) == wxYES) { m_draw.m_bShowElevation = false; CloseProgressDialog(); return; } else ResumeProgressDialog(); } #endif ColorMap cmap; vtString cmap_fname = m_draw.m_strColorMapFile; vtString cmap_path = FindFileOnPaths(vtGetDataPath(), "GeoTypical/" + cmap_fname); bool bLoaded = false; if (cmap_path != "") { if (cmap.Load(cmap_path)) bLoaded = true; } if (!bLoaded) SetupDefaultColors(cmap); bool has_invalid = m_pGrid->ColorDibFromElevation(m_pBitmap, &cmap, 8000, RGBi(255,0,0), progress_callback_minor); if (m_draw.m_bShadingQuick) m_pGrid->ShadeQuick(m_pBitmap, SHADING_BIAS, true, progress_callback_minor); else if (m_draw.m_bShadingDot) { // Quick and simple sunlight vector FPoint3 light_dir = LightDirection(m_draw.m_iCastAngle, m_draw.m_iCastDirection); if (m_draw.m_bCastShadows) m_pGrid->ShadowCastDib(m_pBitmap, light_dir, 1.0f, m_draw.m_fAmbient, progress_callback_minor); else m_pGrid->ShadeDibFromElevation(m_pBitmap, light_dir, 1.0f, m_draw.m_fAmbient, m_draw.m_fGamma, true, progress_callback_minor); } m_pBitmap->ContentsChanged(); if (has_invalid && m_draw.m_bDoMask) { m_pMask = new wxMask(*m_pBitmap->m_pBitmap, wxColour(255, 0, 0)); m_pBitmap->m_pBitmap->SetMask(m_pMask); m_bHasMask = true; } else m_bHasMask = false; clock_t tm2 = clock(); float time = ((float)tm2 - tm1)/CLOCKS_PER_SEC; VTLOG("RenderBitmap: %.3f seconds.\n", time); m_bBitmapRendered = true; }
void vtElevLayer::SetupDefaultColors(ColorMap &cmap) { cmap.m_bRelative = false; cmap.Add(-400*17, RGBi(255, 255, 255)); cmap.Add(-400*16, RGBi(20, 20, 30 )); cmap.Add(-400*15, RGBi(60, 60, 70 )); cmap.Add(-400*14, RGBi(120, 120, 130)); cmap.Add(-400*13, RGBi(180, 185, 190)); cmap.Add(-400*12, RGBi(160, 80, 0 )); cmap.Add(-400*11, RGBi(128, 128, 0 )); cmap.Add(-400*10, RGBi(160, 0, 160 )); cmap.Add(-400* 9, RGBi(144, 64, 144 )); cmap.Add(-400* 8, RGBi(128, 128, 128)); cmap.Add(-400* 7, RGBi(64, 128, 60 )); cmap.Add(-400* 6, RGBi(0, 128, 0 )); cmap.Add(-400* 5, RGBi(0, 128, 128 )); cmap.Add(-400* 4, RGBi(0, 0, 160 )); cmap.Add(-400* 3, RGBi(43, 90, 142 )); cmap.Add(-400* 2, RGBi(81, 121, 172 )); cmap.Add(-400* 1, RGBi(108, 156, 195)); cmap.Add(-1.0f, RGBi(182, 228, 255)); cmap.Add(0, RGBi(0, 0, 0xee)); cmap.Add( 0.1f, RGBi(40, 224, 40 )); cmap.Add( 450* 1, RGBi(0, 128, 0 )); cmap.Add( 450* 2, RGBi(100, 144, 76 )); cmap.Add( 450* 3, RGBi(204, 170, 136)); cmap.Add( 450* 4, RGBi(136, 100, 70 )); cmap.Add( 450* 5, RGBi(128, 128, 128)); cmap.Add( 450* 6, RGBi(180, 128, 64 )); cmap.Add( 450* 7, RGBi(255, 144, 32 )); cmap.Add( 450* 8, RGBi(200, 110, 80 )); cmap.Add( 450* 9, RGBi(160, 80, 160 )); cmap.Add( 450*10, RGBi(144, 40, 128 )); cmap.Add( 450*11, RGBi(128, 128, 128)); cmap.Add( 450*12, RGBi(255, 255, 255)); cmap.Add( 450*13, RGBi(255, 255, 128)); cmap.Add( 450*14, RGBi(255, 128, 0)); cmap.Add( 450*15, RGBi(0, 128, 0)); }
bool vtElevLayer::WriteElevationTileset(TilingOptions &opts, BuilderView *pView) { // Avoid trouble with '.' and ',' in Europe ScopedLocale normal_numbers(LC_NUMERIC, "C"); // Check that options are valid CheckCompressionMethod(opts); // grid size int base_tilesize = opts.lod0size; int gridcols, gridrows; m_pGrid->GetDimensions(gridcols, gridrows); DRECT area = m_pGrid->GetEarthExtents(); DPoint2 tile_dim(area.Width()/opts.cols, area.Height()/opts.rows); DPoint2 cell_size = tile_dim / base_tilesize; const vtProjection &proj = m_pGrid->GetProjection(); vtString units = GetLinearUnitName(proj.GetUnits()); units.MakeLower(); int zone = proj.GetUTMZone(); vtString crs; if (proj.IsGeographic()) crs = "LL"; else if (zone != 0) crs = "UTM"; else crs = "Other"; // Try to create directory to hold the tiles vtString dirname = opts.fname; RemoveFileExtensions(dirname); if (!vtCreateDir(dirname)) return false; // We won't know the exact height extents until the tiles have generated, // so gather extents as we produce the tiles and write the INI later. float minheight = 1E9, maxheight = -1E9; ColorMap cmap; vtElevLayer::SetupDefaultColors(cmap); // defaults vtString dirname_image = opts.fname_images; RemoveFileExtensions(dirname_image); if (opts.bCreateDerivedImages) { if (!vtCreateDir(dirname_image)) return false; vtString cmap_fname = opts.draw.m_strColorMapFile; vtString cmap_path = FindFileOnPaths(vtGetDataPath(), "GeoTypical/" + cmap_fname); if (cmap_path == "") DisplayAndLog("Couldn't find color map."); else { if (!cmap.Load(cmap_path)) DisplayAndLog("Couldn't load color map."); } } ImageGLCanvas *pCanvas = NULL; #if USE_OPENGL wxFrame *frame = new wxFrame; if (opts.bCreateDerivedImages && opts.bUseTextureCompression && opts.eCompressionType == TC_OPENGL) { frame->Create(g_bld->m_pParentWindow, -1, _T("Texture Compression OpenGL Context"), wxPoint(100,400), wxSize(280, 300), wxCAPTION | wxCLIP_CHILDREN); pCanvas = new ImageGLCanvas(frame); } #endif // make a note of which lods exist LODMap lod_existence_map(opts.cols, opts.rows); bool bFloat = m_pGrid->IsFloatMode(); bool bJPEG = (opts.bUseTextureCompression && opts.eCompressionType == TC_JPEG); int i, j, lod; int total = opts.rows * opts.cols, done = 0; for (j = 0; j < opts.rows; j++) { for (i = 0; i < opts.cols; i++) { // We might want to skip certain tiles if (opts.iMinRow != -1 && (i < opts.iMinCol || i > opts.iMaxCol || j < opts.iMinRow || j > opts.iMaxRow)) continue; DRECT tile_area; tile_area.left = area.left + tile_dim.x * i; tile_area.right = area.left + tile_dim.x * (i+1); tile_area.bottom = area.bottom + tile_dim.y * j; tile_area.top = area.bottom + tile_dim.y * (j+1); int col = i; int row = opts.rows-1-j; // draw our progress in the main view if (pView) pView->ShowGridMarks(area, opts.cols, opts.rows, col, opts.rows-1-row); // Extract the highest LOD we need vtElevationGrid base_lod(tile_area, IPoint2(base_tilesize+1, base_tilesize+1), bFloat, proj); bool bAllInvalid = true; bool bAllZero = true; int iNumInvalid = 0; DPoint2 p; int x, y; for (y = base_tilesize; y >= 0; y--) { p.y = area.bottom + (j*tile_dim.y) + ((double)y / base_tilesize * tile_dim.y); for (x = 0; x <= base_tilesize; x++) { p.x = area.left + (i*tile_dim.x) + ((double)x / base_tilesize * tile_dim.x); float fvalue = m_pGrid->GetFilteredValue(p); base_lod.SetFValue(x, y, fvalue); if (fvalue == INVALID_ELEVATION) iNumInvalid++; else { bAllInvalid = false; // Gather height extents if (fvalue < minheight) minheight = fvalue; if (fvalue > maxheight) maxheight = fvalue; } if (fvalue != 0) bAllZero = false; } } // Increment whether we omit or not done++; // If there is no real data there, omit this tile if (bAllInvalid) continue; // Omit all-zero tiles (flat sea-level) if desired if (opts.bOmitFlatTiles && bAllZero) continue; // Now we know this tile will be included, so note the LODs present int base_tile_exponent = vt_log2(base_tilesize); lod_existence_map.set(i, j, base_tile_exponent, base_tile_exponent-(opts.numlods-1)); if (iNumInvalid > 0) { UpdateProgressDialog2(done*99/total, 0, _("Filling gaps")); bool bGood; int method = g_Options.GetValueInt(TAG_GAP_FILL_METHOD); if (method == 1) bGood = base_lod.FillGaps(NULL, progress_callback_minor); else if (method == 2) bGood = base_lod.FillGapsSmooth(NULL, progress_callback_minor); else if (method == 3) bGood = (base_lod.FillGapsByRegionGrowing(2, 5, progress_callback_minor) != -1); if (!bGood) return false; opts.iNoDataFilled += iNumInvalid; } // Create a matching derived texture tileset if (opts.bCreateDerivedImages) { // Create a matching derived texture tileset vtDIB dib; base_lod.ComputeHeightExtents(); if (opts.bImageAlpha) { dib.Create(IPoint2(base_tilesize, base_tilesize), 32); base_lod.ColorDibFromElevation(&dib, &cmap, 4000, RGBAi(0,0,0,0)); } else { dib.Create(IPoint2(base_tilesize, base_tilesize), 24); base_lod.ColorDibFromElevation(&dib, &cmap, 4000, RGBi(255,0,0)); } if (opts.draw.m_bShadingQuick) base_lod.ShadeQuick(&dib, SHADING_BIAS, true); else if (opts.draw.m_bShadingDot) { FPoint3 light_dir = LightDirection(opts.draw.m_iCastAngle, opts.draw.m_iCastDirection); // Don't cast shadows for tileset; they won't cast // correctly from one tile to the next. base_lod.ShadeDibFromElevation(&dib, light_dir, 1.0f, opts.draw.m_fAmbient, opts.draw.m_fGamma, true); } for (int k = 0; k < opts.numlods; k++) { vtString fname = MakeFilenameDB(dirname_image, col, row, k); int tilesize = base_tilesize >> k; vtMiniDatabuf output_buf; output_buf.xsize = tilesize; output_buf.ysize = tilesize; output_buf.zsize = 1; output_buf.tsteps = 1; output_buf.SetBounds(proj, tile_area); int depth = dib.GetDepth() / 8; int iUncompressedSize = tilesize * tilesize * depth; uchar *rgb_bytes = (uchar *) malloc(iUncompressedSize); uchar *dst = rgb_bytes; if (opts.bImageAlpha) { RGBAi rgba; for (int ro = 0; ro < base_tilesize; ro += (1<<k)) for (int co = 0; co < base_tilesize; co += (1<<k)) { dib.GetPixel32(co, ro, rgba); *dst++ = rgba.r; *dst++ = rgba.g; *dst++ = rgba.b; *dst++ = rgba.a; } } else { RGBi rgb; for (int ro = 0; ro < base_tilesize; ro += (1<<k)) for (int co = 0; co < base_tilesize; co += (1<<k)) { dib.GetPixel24(co, ro, rgb); *dst++ = rgb.r; *dst++ = rgb.g; *dst++ = rgb.b; } } // Write and optionally compress the image WriteMiniImage(fname, opts, rgb_bytes, output_buf, iUncompressedSize, pCanvas); // Free the uncompressed image free(rgb_bytes); } } for (lod = 0; lod < opts.numlods; lod++) { int tilesize = base_tilesize >> lod; vtString fname = MakeFilenameDB(dirname, col, row, lod); // make a message for the progress dialog wxString msg; msg.Printf(_("Writing tile '%hs', size %dx%d"), (const char *)fname, tilesize, tilesize); UpdateProgressDialog2(done*99/total, 0, msg); vtMiniDatabuf buf; buf.SetBounds(proj, tile_area); buf.alloc(tilesize+1, tilesize+1, 1, 1, bFloat ? 2 : 1); float *fdata = (float *) buf.data; short *sdata = (short *) buf.data; DPoint2 p; for (int y = base_tilesize; y >= 0; y -= (1<<lod)) { p.y = area.bottom + (j*tile_dim.y) + ((double)y / base_tilesize * tile_dim.y); for (int x = 0; x <= base_tilesize; x += (1<<lod)) { p.x = area.left + (i*tile_dim.x) + ((double)x / base_tilesize * tile_dim.x); if (bFloat) { *fdata = base_lod.GetFilteredValue(p); fdata++; } else { *sdata = (short) base_lod.GetFilteredValue(p); sdata++; } } } if (buf.savedata(fname) == 0) { // what should we do if writing a tile fails? } } } }
void Group::MenuGroup(int id) { Group g; ZERO(&g); g.visible = true; g.color = RGBi(100, 100, 100); g.scale = 1; if(id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT)) { strcpy(g.impFile, RecentFile[id-RECENT_IMPORT]); id = GraphicsWindow::MNU_GROUP_IMPORT; } SS.GW.GroupSelection(); switch(id) { case GraphicsWindow::MNU_GROUP_3D: g.type = DRAWING_3D; g.name.strcpy("sketch-in-3d"); break; case GraphicsWindow::MNU_GROUP_WRKPL: g.type = DRAWING_WORKPLANE; g.name.strcpy("sketch-in-plane"); if(gs.points == 1 && gs.n == 1) { g.subtype = WORKPLANE_BY_POINT_ORTHO; Vector u = SS.GW.projRight, v = SS.GW.projUp; u = u.ClosestOrtho(); v = v.Minus(u.ScaledBy(v.Dot(u))); v = v.ClosestOrtho(); g.predef.q = Quaternion::From(u, v); g.predef.origin = gs.point[0]; } else if(gs.points == 1 && gs.lineSegments == 2 && gs.n == 3) { g.subtype = WORKPLANE_BY_LINE_SEGMENTS; g.predef.origin = gs.point[0]; g.predef.entityB = gs.entity[0]; g.predef.entityC = gs.entity[1]; Vector ut = SK.GetEntity(g.predef.entityB)->VectorGetNum(); Vector vt = SK.GetEntity(g.predef.entityC)->VectorGetNum(); ut = ut.WithMagnitude(1); vt = vt.WithMagnitude(1); if(fabs(SS.GW.projUp.Dot(vt)) < fabs(SS.GW.projUp.Dot(ut))) { SWAP(Vector, ut, vt); g.predef.swapUV = true; } if(SS.GW.projRight.Dot(ut) < 0) g.predef.negateU = true; if(SS.GW.projUp. Dot(vt) < 0) g.predef.negateV = true; } else { Error("Bad selection for new sketch in workplane. This " "group can be created with:\n\n" " * a point (orthogonal to coordinate axes, " "through the point)\n" " * a point and two line segments (parallel to the " "lines, through the point)\n"); return; } break; case GraphicsWindow::MNU_GROUP_EXTRUDE: if(!SS.GW.LockedInWorkplane()) { Error("Select a workplane (Sketch -> In Workplane) before " "extruding. The sketch will be extruded normal to the " "workplane."); return; } g.type = EXTRUDE; g.opA = SS.GW.activeGroup; g.predef.entityB = SS.GW.ActiveWorkplane(); g.subtype = ONE_SIDED; g.name.strcpy("extrude"); break; case GraphicsWindow::MNU_GROUP_LATHE: if(gs.points == 1 && gs.vectors == 1 && gs.n == 2) { g.predef.origin = gs.point[0]; g.predef.entityB = gs.vector[0]; } else if(gs.lineSegments == 1 && gs.n == 1) { g.predef.origin = SK.GetEntity(gs.entity[0])->point[0]; g.predef.entityB = gs.entity[0]; // since a line segment is a vector } else { Error("Bad selection for new lathe group. This group can " "be created with:\n\n" " * a point and a line segment or normal " "(revolved about an axis parallel to line / " "normal, through point)\n" " * a line segment (revolved about line segment)\n"); return; } g.type = LATHE; g.opA = SS.GW.activeGroup; g.name.strcpy("lathe"); break; case GraphicsWindow::MNU_GROUP_ROT: { if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) { g.predef.origin = gs.point[0]; Entity *w = SK.GetEntity(SS.GW.ActiveWorkplane()); g.predef.entityB = w->Normal()->h; g.activeWorkplane = w->h; } else if(gs.points == 1 && gs.vectors == 1 && gs.n == 2) { g.predef.origin = gs.point[0]; g.predef.entityB = gs.vector[0]; } else { Error("Bad selection for new rotation. This group can " "be created with:\n\n" " * a point, while locked in workplane (rotate " "in plane, about that point)\n" " * a point and a line or a normal (rotate about " "an axis through the point, and parallel to " "line / normal)\n"); return; } g.type = ROTATE; g.opA = SS.GW.activeGroup; g.valA = 3; g.subtype = ONE_SIDED; g.name.strcpy("rotate"); break; } case GraphicsWindow::MNU_GROUP_TRANS: g.type = TRANSLATE; g.opA = SS.GW.activeGroup; g.valA = 3; g.subtype = ONE_SIDED; g.predef.entityB = SS.GW.ActiveWorkplane(); g.activeWorkplane = SS.GW.ActiveWorkplane(); g.name.strcpy("translate"); break; case GraphicsWindow::MNU_GROUP_IMPORT: { g.type = IMPORTED; g.opA = SS.GW.activeGroup; if(strlen(g.impFile) == 0) { if(!GetOpenFile(g.impFile, SLVS_EXT, SLVS_PATTERN)) return; } // Assign the default name of the group based on the name of // the imported file. char groupName[MAX_PATH]; strcpy(groupName, g.impFile); char *dot = strrchr(groupName, '.'); if(dot) *dot = '\0'; char *s, *start = groupName; for(s = groupName; *s; s++) { if(*s == '/' || *s == '\\') { start = s + 1; } else if(isalnum(*s)) { // do nothing, valid character } else { // convert invalid characters (like spaces) to dashes *s = '-'; } } if(strlen(start) > 0) { g.name.strcpy(start); } else { g.name.strcpy("import"); } g.meshCombine = COMBINE_AS_ASSEMBLE; break; } default: oops(); } SS.GW.ClearSelection(); SS.UndoRemember(); SK.group.AddAndAssignId(&g); Group *gg = SK.GetGroup(g.h); if(gg->type == IMPORTED) { SS.ReloadAllImported(); } gg->clean = false; SS.GW.activeGroup = gg->h; SS.GenerateAll(); if(gg->type == DRAWING_WORKPLANE) { // Can't set the active workplane for this one until after we've // regenerated, because the workplane doesn't exist until then. gg->activeWorkplane = gg->h.entity(0); } gg->Activate(); SS.GW.AnimateOntoWorkplane(); TextWindow::ScreenSelectGroup(0, gg->h.v); SS.later.showTW = true; }
void StructVisitorGML::startElement(const char *name, const XMLAttributes &atts) { const char *attval; float f; // clear data at the start of each element m_data = ""; if (m_state == 0 && !strcmp(name, "StructureCollection")) { m_state = 1; return; } if (m_state == 1) { if (!strcmp(name, "Building")) { m_pBuilding = m_pSA->NewBuilding(); m_pStructure = m_pBuilding; m_state = 2; m_iLevel = 0; } else if (!strcmp(name, "Linear")) { m_pFence = m_pSA->NewFence(); m_pFence->GetParams().Blank(); m_pStructure = m_pFence; // support obsolete attribute attval = atts.getValue("Height"); if (attval) { f = (float) atof(attval); m_pFence->GetParams().m_fPostHeight = f; m_pFence->GetParams().m_fConnectTop = f; } m_state = 10; } else if (!strcmp(name, "Imported")) { m_pInstance = m_pSA->NewInstance(); m_pStructure = m_pInstance; m_state = 20; } attval = atts.getValue("ElevationOffset"); if (attval) m_pStructure->SetElevationOffset((float) atof(attval)); attval = atts.getValue("Absolute"); if (attval) m_pStructure->SetAbsolute(*attval == 't'); return; } if (m_state == 2) // Building { if (!strcmp(name, "Level")) { m_pLevel = m_pBuilding->CreateLevel(); attval = atts.getValue("FloorHeight"); if (attval) m_pLevel->m_fStoryHeight = (float) atof(attval); attval = atts.getValue("StoryCount"); if (attval) m_pLevel->m_iStories = atoi(attval); m_state = 3; m_iEdge = 0; } return; } if (m_state == 3) // Level { if (!strcmp(name, "Footprint")) { m_state = 4; m_Footprint.clear(); } else if (!strcmp(name, "Edge")) { m_pEdge = m_pLevel->GetEdge(m_iEdge); if (m_pEdge) // safety check { m_pEdge->m_Features.clear(); attval = atts.getValue("Material"); if (attval) { vtMaterialDescriptorArray *mats = GetGlobalMaterials(); m_pEdge->m_pMaterial = mats->FindName(attval); if (m_pEdge->m_pMaterial == NULL) { // What to do when a VTST references a material that // we don't have? We don't want to lose the material // name information, and we also don't want to crash // later with a NULL material. So, make a dummy. vtMaterialDescriptor *mat; mat = new vtMaterialDescriptor(attval, "", VT_MATERIAL_COLOUR); mat->SetRGB(RGBi(255,255,255)); // white means: missing mats->Append(mat); m_pEdge->m_pMaterial = &mat->GetName(); } } attval = atts.getValue("Color"); if (attval) m_pEdge->m_Color = ParseHexColor(attval); attval = atts.getValue("Slope"); if (attval) m_pEdge->m_iSlope = atoi(attval); attval = atts.getValue("EaveLength"); if (attval) m_pEdge->m_fEaveLength = (float) atof(attval); attval = atts.getValue("Facade"); if (attval) m_pEdge->m_Facade = attval; } m_state = 7; // in Edge } return; } if (m_state == 4) // Footprint { if (!strcmp(name, "gml:outerBoundaryIs")) m_state = 5; if (!strcmp(name, "gml:innerBoundaryIs")) m_state = 6; } if (m_state == 5) // Footprint outerBoundaryIs { // nothing necessary here, catch the end of element } if (m_state == 6) // Footprint innerBoundaryIs { // nothing necessary here, catch the end of element } if (m_state == 7) // Edge { if (!strcmp(name, "EdgeElement")) { vtEdgeFeature ef; attval = atts.getValue("Type"); if (attval) ef.m_code = vtBuilding::GetEdgeFeatureValue(attval); attval = atts.getValue("Begin"); if (attval) ef.m_vf1 = (float) atof(attval); attval = atts.getValue("End"); if (attval) ef.m_vf2 = (float) atof(attval); if (m_pEdge) m_pEdge->m_Features.push_back(ef); } } if (m_state == 10) // Linear { vtLinearParams ¶m = m_pFence->GetParams(); if (!strcmp(name, "Path")) { m_state = 11; } else if (!strcmp(name, "Posts")) { // this linear structure has posts const char *type = atts.getValue("Type"); if (type) param.m_PostType = type; else param.m_PostType = "none"; const char *spacing = atts.getValue("Spacing"); if (spacing) param.m_fPostSpacing = (float)atof(spacing); const char *height = atts.getValue("Height"); if (height) param.m_fPostHeight = (float)atof(height); const char *size = atts.getValue("Size"); if (size) { FPoint3 postsize; sscanf(size, "%f, %f", &postsize.x, &postsize.z); param.m_fPostWidth = postsize.x; param.m_fPostDepth = postsize.z; } const char *exten = atts.getValue("Extension"); if (exten) param.m_PostExtension = exten; } else if (!strcmp(name, "Connect")) { const char *type = atts.getValue("Type"); if (type) { // Older format version had string "none", "wire", or a material for type // Newer format has integer 0,1,2,3 for none,wire,simple,profile if (*type >= '0' && *type <= '9') param.m_iConnectType = atoi(type); else { // Convert old to new if (!strcmp(type, "none")) param.m_iConnectType = 0; else if (!strcmp(type, "wire")) param.m_iConnectType = 1; else { param.m_iConnectType = 2; param.m_ConnectMaterial = type; } } } else param.m_iConnectType = 0; attval = atts.getValue("Material"); if (attval) param.m_ConnectMaterial = attval; attval = atts.getValue("Top"); if (attval) param.m_fConnectTop = (float)atof(attval); attval = atts.getValue("Bottom"); if (attval) param.m_fConnectBottom = (float)atof(attval); attval = atts.getValue("Width"); if (attval) param.m_fConnectWidth = (float)atof(attval); attval = atts.getValue("Slope"); if (attval) param.m_iConnectSlope = atoi(attval); attval = atts.getValue("ConstantTop"); if (attval) param.m_bConstantTop = (*attval == 't'); attval = atts.getValue("Profile"); if (attval) param.m_ConnectProfile = attval; } } if (m_state == 20) // Imported { if (!strcmp(name, "Location")) { m_state = 21; } } }
void Entity::DrawOrGetDistance(void) { if(!IsVisible()) return; Group *g = SK.GetGroup(group); switch(type) { case POINT_N_COPY: case POINT_N_TRANS: case POINT_N_ROT_TRANS: case POINT_N_ROT_AA: case POINT_IN_3D: case POINT_IN_2D: { Vector v = PointGetNum(); dogd.refp = v; if(dogd.drawing) { double s = 3.5; Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale); Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale); ssglColorRGB(Style::Color(Style::DATUM)); ssglDepthRangeOffset(6); glBegin(GL_QUADS); ssglVertex3v(v.Plus (r).Plus (d)); ssglVertex3v(v.Plus (r).Minus(d)); ssglVertex3v(v.Minus(r).Minus(d)); ssglVertex3v(v.Minus(r).Plus (d)); glEnd(); ssglDepthRangeOffset(0); } else { Point2d pp = SS.GW.ProjectPoint(v); dogd.dmin = pp.DistanceTo(dogd.mp) - 6; } break; } case NORMAL_N_COPY: case NORMAL_N_ROT: case NORMAL_N_ROT_AA: case NORMAL_IN_3D: case NORMAL_IN_2D: { int i; for(i = 0; i < 2; i++) { if(i == 0 && !SS.GW.showNormals) { // When the normals are hidden, we will continue to show // the coordinate axes at the bottom left corner, but // not at the origin. continue; } hRequest hr = h.request(); // Always draw the x, y, and z axes in red, green, and blue; // brighter for the ones at the bottom left of the screen, // dimmer for the ones at the model origin. int f = (i == 0 ? 100 : 255); if(hr.v == Request::HREQUEST_REFERENCE_XY.v) { ssglColorRGB(RGBi(0, 0, f)); } else if(hr.v == Request::HREQUEST_REFERENCE_YZ.v) { ssglColorRGB(RGBi(f, 0, 0)); } else if(hr.v == Request::HREQUEST_REFERENCE_ZX.v) { ssglColorRGB(RGBi(0, f, 0)); } else { ssglColorRGB(Style::Color(Style::NORMALS)); if(i > 0) break; } Quaternion q = NormalGetNum(); Vector tail; if(i == 0) { tail = SK.GetEntity(point[0])->PointGetNum(); glLineWidth(1); } else { // Draw an extra copy of the x, y, and z axes, that's // always in the corner of the view and at the front. // So those are always available, perhaps useful. double s = SS.GW.scale; double h = 60 - SS.GW.height/2; double w = 60 - SS.GW.width/2; tail = SS.GW.projRight.ScaledBy(w/s).Plus( SS.GW.projUp. ScaledBy(h/s)).Minus(SS.GW.offset); ssglDepthRangeLockToFront(true); glLineWidth(2); } Vector v = (q.RotationN()).WithMagnitude(50/SS.GW.scale); Vector tip = tail.Plus(v); LineDrawOrGetDistance(tail, tip); v = v.WithMagnitude(12/SS.GW.scale); Vector axis = q.RotationV(); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis, 0.6))); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis,-0.6))); } ssglDepthRangeLockToFront(false); break; } case DISTANCE: case DISTANCE_N_COPY: // These are used only as data structures, nothing to display. break; case WORKPLANE: { Vector p; p = SK.GetEntity(point[0])->PointGetNum(); Vector u = Normal()->NormalU(); Vector v = Normal()->NormalV(); double s = (min(SS.GW.width, SS.GW.height))*0.45/SS.GW.scale; Vector us = u.ScaledBy(s); Vector vs = v.ScaledBy(s); Vector pp = p.Plus (us).Plus (vs); Vector pm = p.Plus (us).Minus(vs); Vector mm = p.Minus(us).Minus(vs), mm2 = mm; Vector mp = p.Minus(us).Plus (vs); glLineWidth(1); ssglColorRGB(Style::Color(Style::NORMALS)); glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0x1111); if(!h.isFromRequest()) { mm = mm.Plus(v.ScaledBy(60/SS.GW.scale)); mm2 = mm2.Plus(u.ScaledBy(60/SS.GW.scale)); LineDrawOrGetDistance(mm2, mm); } LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pm, mm2); LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mp, pp); glDisable(GL_LINE_STIPPLE); char *str = DescriptionString()+5; double th = DEFAULT_TEXT_HEIGHT; if(dogd.drawing) { ssglWriteText(str, th, mm2, u, v, NULL, NULL); } else { Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus( v.ScaledBy(ssglStrHeight(th)/2)); Point2d pp = SS.GW.ProjectPoint(pos); dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10); // If a line lies in a plane, then select the line, not // the plane. dogd.dmin += 3; } break; } case LINE_SEGMENT: case CIRCLE: case ARC_OF_CIRCLE: case CUBIC: case CUBIC_PERIODIC: case TTF_TEXT: // Nothing but the curve(s). break; case FACE_NORMAL_PT: case FACE_XPROD: case FACE_N_ROT_TRANS: case FACE_N_TRANS: case FACE_N_ROT_AA: // Do nothing; these are drawn with the triangle mesh break; default: oops(); } // And draw the curves; generate the rational polynomial curves for // everything, then piecewise linearize them, and display those. SEdgeList sel; ZERO(&sel); GenerateEdges(&sel, true); int i; for(i = 0; i < sel.l.n; i++) { SEdge *se = &(sel.l.elem[i]); LineDrawOrGetDistance(se->a, se->b, true); } sel.Clear(); }