double vtIcoGlobe::AddSurfaceLineToMesh(vtGeomFactory *pMF, const DLine2 &line) { DPoint2 g1, g2; DPoint3 p1, p2; double scale = 1.0002; int length = 0; DMatrix3 rot3; pMF->PrimStart(); int i, j, size = line.GetSize(); for (i = 0; i < size-1; i++) { g1 = line.GetAt(i); g2 = line.GetAt(i+1); // for each pair of points, determine how many more points are needed // for a smooth arc geo_to_xyz(1.0, g1, p1); geo_to_xyz(1.0, g2, p2); double angle = acos(p1.Dot(p2)); int segments = (int) (angle * 2000); if (segments < 1) segments = 1; if (segments > 1) { // calculate the axis of rotation DPoint3 cross = p1.Cross(p2); cross.Normalize(); rot3.AxisAngle(cross, angle / segments); } // curved arc on great-circle path for (j = 0; j < segments; j++) { FPoint3 fp = p1 * 1.0002; pMF->AddVertex(fp); length++; if (j < segments-1) { rot3.Transform(p1, p2); p1 = p2; } } } // last vertex if (size > 1) { g2 = line.GetAt(size-1); geo_to_xyz(1.0, g2, p2); pMF->AddVertex(p2 * scale); length++; } pMF->PrimEnd(); return 0.0; }
void vtStructureArray::Offset(const DPoint2 &delta) { uint npoints = GetSize(); if (!npoints) return; uint i, j; DPoint2 temp; for (i = 0; i < npoints; i++) { vtStructure *str = GetAt(i); vtBuilding *bld = str->GetBuilding(); if (bld) bld->Offset(delta); vtFence *fen = str->GetFence(); if (fen) { DLine2 line = fen->GetFencePoints(); for (j = 0; j < line.GetSize(); j++) line.GetAt(j) += delta; } vtStructInstance *inst = str->GetInstance(); if (inst) inst->Offset(delta); } }
void DymaxIcosa::AddFlatTri(DLine2Array &polys, int a, int b, int c, int d) { DLine2 poly; poly.Append(m_flatverts[a]); poly.Append(m_flatverts[b]); poly.Append(m_flatverts[c]); if (d != -1) poly.Append(m_flatverts[d]); polys.push_back(poly); }
/** * Sets the base footprint of the building to be a circle. A circle * is represented by a 20-sided polygonal footprint. * * \param center The location of the building's center. * \param fRad The radius of the building. */ void vtBuilding::SetCircle(const DPoint2 ¢er, float fRad) { DLine2 fp; int i; for (i = 0; i < 20; i++) { double angle = i * PI2d / 20; DPoint2 vec(cos(angle) * fRad, sin(angle) * fRad); fp.Append(center + vec); } SetFootprint(0, fp); }
// // Make a polyline for this vtLine by using the points from each node. // void vtLine::MakePolyline(DLine2 &polyline) { const uint num = m_poles.size(); polyline.SetSize(num); for (uint i = 0; i < num; i++) polyline[i] = m_poles[i]->m_p; }
void vtLevel::SetFootprint(const DLine2 &dl) { // Safety check: Make sure there is at least an outer polygon if (m_Foot.size() == 0) m_Foot.resize(1); int prev = m_Foot[0].GetSize(); m_Foot[0] = dl; int curr = dl.GetSize(); if (curr != prev) RebuildEdges(curr); }
bool PolyChecker::IsSimplePolygon(const DLine2 &vertices) { int iSize = vertices.GetSize(); int i,j; for (i = 0; i < iSize - 2; i++) for (j = i + 2; j < (i == 0 ? iSize - 1 : iSize); j++) if (Intersect(vertices[i], vertices[(i + 1) % iSize], vertices[j], vertices[(j+ 1) % iSize])) return false; return true; }
void DLine2FromString(const char *data, DLine2 &line) { // Speed/memory optimization: quick check of how many vertices // there are, then preallocate that many uint verts = 0; for (size_t i = 0; i < strlen(data); i++) if (data[i] == ',') verts++; line.Empty(); line.SetMaxSize(verts); double x, y; while (sscanf(data, "%lf,%lf", &x, &y) == 2) { line.Append(DPoint2(x,y)); data = strchr(data, ' '); if (!data) break; data++; } }
void vtBuilding::SetRectangle(const DPoint2 ¢er, float fWidth, float fDepth, float fRotation) { vtLevel *pLev; // this function requires at least one level to exist if (m_Levels.GetSize() == 0) { pLev = new vtLevel; pLev->m_iStories = 1; m_Levels.Append(pLev); } else pLev = m_Levels[0]; // if rotation is unset, default to none if (fRotation == -1.0f) fRotation = 0.0f; DPoint2 pt(fWidth / 2.0, fDepth / 2.0); DPoint2 corner[4]; corner[0].Set(-pt.x, -pt.y); corner[1].Set(pt.x, -pt.y); corner[2].Set(pt.x, pt.y); corner[3].Set(-pt.x, pt.y); corner[0].Rotate(fRotation); corner[1].Rotate(fRotation); corner[2].Rotate(fRotation); corner[3].Rotate(fRotation); DLine2 dl; dl.Append(center + corner[0]); dl.Append(center + corner[1]); dl.Append(center + corner[2]); dl.Append(center + corner[3]); pLev->SetFootprint(dl); }
bool PolyChecker::IsClockwisePolygon(const DLine2 &vertices) { DPoint2 p1, p2; int iSize = vertices.GetSize(); // Cannot remember if this works for all Jordan double Area = 0; for (int i = 0; i < iSize; i++) { p1 = vertices[i]; p2 = vertices[(i+1)%iSize]; Area += (p2.x - p1.x) * (p2.y + p1.y); } if (Area > 0) return true; else return false; }
/** * Create a set of points on the heightfield for a 2D polyline by draping the point onto * the surface. * * \param line The 2D line to drape, in Earth coordinates. * \param fSpacing The approximate spacing of the surface tessellation, used to * decide how finely to tessellate the line. * \param fOffset An offset to elevate each point in the resulting geometry, * useful for keeping it visibly above the ground. * \param bInterp True to interpolate between the vertices of the input * line. This is generally desirable when the ground is much more finely * spaced than the input line. * \param bCurve True to interpret the vertices of the input line as * control points of a curve. The created geometry will consist of * a draped line which passes through the control points. * \param bTrue True to use the true elevation of the terrain, ignoring * whatever scale factor is being used to exaggerate elevation for * display. * \param output Received the points. * \return The approximate length of the resulting 3D polyline. */ float vtHeightField3d::LineOnSurface(const DLine2 &line, float fSpacing, float fOffset, bool bInterp, bool bCurve, bool bTrue, FLine3 &output) { uint i, j; FPoint3 v1, v2, v; float fTotalLength = 0.0f; int iVerts = 0; uint points = line.GetSize(); if (bCurve) { DPoint2 p2, last(1E9,1E9); DPoint3 p3; int spline_points = 0; CubicSpline spline; for (i = 0; i < points; i++) { p2 = line[i]; if (i > 1 && p2 == last) continue; p3.Set(p2.x, p2.y, 0); spline.AddPoint(p3); spline_points++; last = p2; } spline.Generate(); // Estimate how many steps to subdivide this line into const double dLinearLength = line.Length(); float fLinearLength, dummy; m_LocalCS.VectorEarthToLocal(DPoint2(dLinearLength, 0.0), fLinearLength, dummy); double full = (double) (spline_points-1); int iSteps = (uint) (fLinearLength / fSpacing); if (iSteps < 3) iSteps = 3; double dStep = full / iSteps; FPoint3 last_v; for (double f = 0; f <= full; f += dStep) { spline.Interpolate(f, &p3); m_LocalCS.EarthToLocal(p3.x, p3.y, v.x, v.z); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); iVerts++; // keep a running total of approximate ground length if (f > 0) fTotalLength += (v - last_v).Length(); last_v = v; } } else { // not curved: straight line in earth coordinates FPoint3 last_v; for (i = 0; i < points; i++) { if (bInterp) { v1 = v2; m_LocalCS.EarthToLocal(line[i].x, line[i].y, v2.x, v2.z); if (i == 0) continue; // estimate how many steps to subdivide this segment into FPoint3 diff = v2 - v1; float fLen = diff.Length(); uint iSteps = (uint) (fLen / fSpacing); if (iSteps < 1) iSteps = 1; for (j = (i == 1 ? 0:1); j <= iSteps; j++) { // simple linear interpolation of the ground coordinate v.Set(v1.x + diff.x / iSteps * j, 0.0f, v1.z + diff.z / iSteps * j); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); iVerts++; // keep a running total of approximate ground length if (j > 0) fTotalLength += (v - last_v).Length(); last_v = v; } } else { m_LocalCS.EarthToLocal(line[i], v.x, v.z); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); } } } return fTotalLength; }
void vtVegLayer::AddElementsFromLULC(vtLULCFile *pLULC) { LULCSection *section; LULCPoly *poly; SetVegType(VLT_Density); //set projections vtProjection proj_new; proj_new.SetProjectionSimple(0, -1, EPSG_DATUM_WGS84); SetProjection(proj_new); // figure out the number of polygons in file uint size = 0; for (uint sec = 0; sec < pLULC->NumSections(); sec++) { section = pLULC->GetSection(sec); size = size + section->m_iNumPolys; } // Create density field m_field_density = m_pSet->AddField("Density", FT_Float); m_pSet->SetNumEntities(size); // get each poly from LULC file uint i, s, p, count = 0; float density=0; for (s = 0; s < pLULC->NumSections(); s++) { section = pLULC->GetSection(s); for (p = 0; p < section->m_iNumPolys; p++) { poly = section->m_pPoly + p; bool wild = false; switch (poly->Attribute) { case 42: // forest wild = true; density = 1.0f; break; case 32: case 33: wild = true; density = 0.5; break; case 22: // orchards wild = false; // no crops for now break; default: density = 0.0f; break; } DLine2 dline; dline.SetSize(poly->m_iCoords); // get Coords of LULCpoly and store as latlon, then save in VPoly for (i = 0; i < dline.GetSize(); i++) dline.SetAt(i, poly->m_p[i]); DPolygon2 dpoly; dpoly.push_back(dline); GetPS()->SetPolygon(count, dpoly); m_pSet->SetValue(count, m_field_density, density); count++; } } }
/** * Combine all vertices which are at the same location. By removing these * redundant vertices, the mesh will consume less space in memory and on disk. */ void vtTin::MergeSharedVerts(bool progress_callback(int)) { uint verts = NumVerts(); uint i, j; int bin; DRECT rect = m_EarthExtents; double width = rect.Width(); // make it slightly larger avoid edge condition rect.left -= 0.000001; width += 0.000002; m_bReplace = new int[verts]; m_vertbin = new Bin[BINS]; m_tribin = new Bin[BINS]; // sort the vertices into bins for (i = 0; i < verts; i++) { // flag all vertices initially not to remove m_bReplace[i] = -1; // find the correct bin, and add the index of this vertex to it bin = (int) (BINS * (m_vert[i].x - rect.left) / width); m_vertbin[bin].push_back(i); } uint trisize = m_tri.size(); for (i = 0; i < trisize; i++) { // find the correct bin, and add the index of this index to it bin = (int) (BINS * (m_vert[m_tri[i]].x - rect.left) / width); m_tribin[bin].push_back(i); } // compare within each bin, and between each adjacent bin, // looking for matching vertices to flag for removal for (bin = 0; bin < BINS; bin++) { if (progress_callback != NULL) progress_callback(bin * 100 / BINS); _CompareBins(bin, bin); if (bin < BINS-1) _CompareBins(bin, bin+1); } // now update each triangle index to point to the merge result for (bin = 0; bin < BINS; bin++) { if (progress_callback != NULL) progress_callback(bin * 100 / BINS); _UpdateIndicesInInBin(bin); } // now compact the vertex bins into a single array // make a copy to copy from DLine2 *vertcopy = new DLine2(m_vert); float *zcopy = new float[m_z.size()]; for (i = 0; i < m_z.size(); i++) zcopy[i] = m_z[i]; int inew = 0; // index into brand new array (actually re-using old) for (bin = 0; bin < BINS; bin++) { if (progress_callback != NULL) progress_callback(bin * 100 / BINS); uint binverts = m_vertbin[bin].size(); for (i = 0; i < binverts; i++) { int v_old = m_vertbin[bin].at(i); if (m_bReplace[v_old] != -1) continue; int v_new = inew; // copy old to new m_vert[v_new] = vertcopy->GetAt(v_old); m_z[v_new] = zcopy[v_old]; uint bintris = m_tribin[bin].size(); for (j = 0; j < bintris; j++) { int trindx = m_tribin[bin].at(j); if (m_tri[trindx] == v_old) m_tri[trindx] = v_new; } inew++; } } // our original array containers now hold the compacted result int newsize = inew; m_vert.SetSize(newsize); m_z.resize(newsize); // free up all the stuff we allocated delete [] m_bReplace; delete [] m_vertbin; delete [] m_tribin; delete vertcopy; delete [] zcopy; }
void StructureVisitor::startElement (const char * name, const XMLAttributes &atts) { int i; if (_level == 0) { if (string(name) != (string)"structures-file") { string message = "Root element name is "; message += name; message += "; expected structures-file"; throw xh_io_exception(message, "XML Reader"); } push_state(NULL, "top"); return; } if (_level == 1) { if (string(name) == (string)"coordinates") { const char *type = atts.getValue("type"); const char *value = atts.getValue("value"); m_pSA->m_proj.SetTextDescription(type, value); g_Conv.Setup(m_pSA->m_proj.GetUnits(), DRECT(0,1,1,0)); } else if (string(name) == (string)"structures") { push_state(NULL, "structures"); } else { // Unknown element: ignore push_state(NULL, "dummy"); } return; } const char *attval; if (_level == 2) { vtStructure *pStruct = NULL; if (string(name) == (string)"structure") { // Get the name. attval = atts.getValue("type"); if (attval != NULL) { if (string(attval) == (string)"building") { vtBuilding *bld = m_pSA->NewBuilding(); pStruct = bld; } if (string(attval) == (string)"linear") { vtFence *fen = m_pSA->NewFence(); pStruct = fen; } if (string(attval) == (string)"instance") { vtStructInstance *inst = m_pSA->NewInstance(); pStruct = inst; } } push_state(pStruct, "structure"); } else { // Unknown field, ignore. pStruct = NULL; push_state(pStruct, "dummy"); } return; } State &st = state(); vtStructure *pStruct = st.item; if (!pStruct) return; vtFence *fen = pStruct->GetFence(); vtBuilding *bld = pStruct->GetBuilding(); vtStructInstance *inst = pStruct->GetInstance(); if (_level == 3 && bld != NULL) { if (string(name) == (string)"height") { attval = atts.getValue("stories"); if (attval) { // height in stories ("floors") int stories = atoi(attval); if (bld) bld->SetStories(stories); } } if (string(name) == (string)"walls") { attval = atts.getValue("color"); if (bld && attval) st.wall_color = ParseRGB(attval); } if (string(name) == (string)"shapes") { push_state(pStruct, "shapes"); return; } if (string(name) == (string)"roof") { // hack to postpone setting building color until now bld->SetColor(BLD_BASIC, st.wall_color); const char *type = atts.getValue("type"); if (bld && (string)type == (string)"flat") bld->SetRoofType(ROOF_FLAT); if (bld && (string)type == (string)"shed") bld->SetRoofType(ROOF_SHED); if (bld && (string)type == (string)"gable") bld->SetRoofType(ROOF_GABLE); if (bld && (string)type == (string)"hip") bld->SetRoofType(ROOF_HIP); attval = atts.getValue("color"); if (bld && attval) bld->SetColor(BLD_ROOF, ParseRGB(attval)); } if (string(name) == (string)"points") { attval = atts.getValue("num"); } return; } if (_level == 3 && fen != NULL) { if (string(name) == (string)"points") { int points; const char *num = atts.getValue("num"); points = atoi(num); DLine2 &fencepts = fen->GetFencePoints(); DPoint2 loc; const char *coords = atts.getValue("coords"); const char *cp = coords; for (i = 0; i < points; i++) { sscanf(cp, "%lf %lf", &loc.x, &loc.y); fencepts.Append(loc); cp = strchr(cp, ' '); cp++; cp = strchr(cp, ' '); cp++; } } if (string(name) == (string)"height") { // absolute height in meters const char *abs_str = atts.getValue("abs"); if (abs_str) fen->GetParams().m_fPostHeight = (float)atof(abs_str); } if (string(name) == (string)"posts") { // this linear structure has posts const char *type = atts.getValue("type"); if (0 == strcmp(type, "wood")) fen->ApplyStyle(FS_WOOD_POSTS_WIRE); else if (0 == strcmp(type, "steel")) fen->ApplyStyle(FS_CHAINLINK); else fen->ApplyStyle(FS_METAL_POSTS_WIRE); const char *size = atts.getValue("size"); FPoint3 postsize; postsize.y = fen->GetParams().m_fPostHeight; sscanf(size, "%f, %f", &postsize.x, &postsize.z); fen->GetParams().m_fPostWidth = postsize.x; fen->GetParams().m_fPostDepth = postsize.z; const char *spacing = atts.getValue("spacing"); if (spacing) fen->GetParams().m_fPostSpacing = (float)atof(spacing); } if (string(name) == (string)"connect") { attval = atts.getValue("type"); // not supported here } return; } if (_level == 3 && inst != NULL) { if (string(name) == (string)"placement") { const char *loc = atts.getValue("location"); if (loc) { DPoint2 p; sscanf(loc, "%lf %lf", &p.x, &p.y); inst->SetPoint(p); } const char *rot = atts.getValue("rotation"); if (rot) { float fRot; sscanf(rot, "%f", &fRot); inst->SetRotation(fRot); } } else _data = ""; } if (_level == 4 && bld != NULL) { if (string(name) == (string)"rect") { DPoint2 loc; FPoint2 size2; const char *ref_point = atts.getValue("ref_point"); if (ref_point) { sscanf(ref_point, "%lf %lf", &loc.x, &loc.y); bld->SetRectangle(loc, 10, 10); } float fRotation = 0.0f; const char *rot = atts.getValue("rot"); if (rot) { fRotation = (float)atof(rot); } const char *size = atts.getValue("size"); if (size) { sscanf(size, "%f, %f", &size2.x, &size2.y); bld->SetRectangle(loc, size2.x, size2.y, fRotation); } } if (string(name) == (string)"circle") { DPoint2 loc; const char *ref_point = atts.getValue("ref_point"); if (ref_point) { sscanf(ref_point, "%lf %lf", &loc.x, &loc.y); bld->SetCircle(loc, 10); } const char *radius = atts.getValue("radius"); if (radius) { bld->SetCircle(loc, (float)atof(radius)); } } if (string(name) == (string)"poly") { int points; const char *num = atts.getValue("num"); points = atoi(num); DLine2 foot; DPoint2 loc; const char *coords = atts.getValue("coords"); const char *cp = coords; for (i = 0; i < points; i++) { sscanf(cp, "%lf %lf", &loc.x, &loc.y); foot.Append(loc); cp = strchr(cp, ' '); cp++; cp = strchr(cp, ' '); cp++; } bld->SetFootprint(0, foot); } } }