Hi everyone,
I’m working on a osm 2d map in the unreal engine to display roads and other things. For that I’m putting a mesh between 2 waypoint of one street section and rotate it and scale it by the half of the road size. But something seems wrong and I can’t figure it out why.
Thank you.
void AGeoMap::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bConnectedSuccess) {
if (Response->GetResponseCode() != 200) {
UE_LOG(LogTemp, Warning, TEXT("RESPONSE CODE: %d"), Response->GetResponseCode());
UE_LOG(LogTemp, Error, TEXT("RESPONSE CODE: %s"), *Response->GetContentAsString());
return;
};
UE_LOG(LogTemp, Display, TEXT("%s"), *Response->GetContentAsString());
TSharedPtr<FJsonObject> jsonObject;
const FString response = *Response->GetContentAsString();
TSharedRef<TJsonReader<>> reader = TJsonReaderFactory<>::Create(response);
if (FJsonSerializer::Deserialize(reader, jsonObject)) {
for (const TSharedPtr<FJsonValue> element : jsonObject->GetArrayField("elements")) {
GenerateRoads(element);
}
}
if (!cMapObjects.IsEmpty())
ClearMapCache();
}
void AGeoMap::GenerateRoads(TSharedPtr<FJsonValue> element) {
if (element->AsObject()->GetStringField("type") != "way")
return;
GenerateGeometry(element->AsObject()->GetArrayField("geometry"), roadThickness);
}
void AGeoMap::GenerateGeometry(TArray<TSharedPtr<FJsonValue>> geoms, float thickness) {
for (size_t i = 0; i < geoms.Num(); i += 2) {
if (i != geoms.Num() - 1) {
FVector2d start = FVector2d(geoms[i]->AsObject()->GetNumberField("lon"), geoms[i]->AsObject()->GetNumberField("lat"));
FVector2d end = FVector2d(geoms[i + 1]->AsObject()->GetNumberField("lon"), geoms[i + 1]->AsObject()->GetNumberField("lat"));
CreateObject(start, end, thickness);
}
else {
FVector2d start = FVector2d(geoms[i - 1]->AsObject()->GetNumberField("lon"), geoms[i - 1]->AsObject()->GetNumberField("lat"));
FVector2d end = FVector2d(geoms[i]->AsObject()->GetNumberField("lon"), geoms[i]->AsObject()->GetNumberField("lat"));
CreateObject(start, end, thickness);
}
}
}
void AGeoMap::CreateObject(FVector2d start, FVector2d end, float thickness) {
start *= mapSize;
end *= mapSize;
double angleToNextPoint = FMath::RadiansToDegrees(FMath::Atan2(end.Y - start.Y, end.X - start.X));
double lengthBetween = CalculateWorldDistance(start.Y, start.X, end.Y, end.X) * 0.5;
FActorSpawnParameters spawnInfo;
AMapObject* mapObject = GetWorld()->SpawnActor<AMapObject>(FVector(-0.1f, (start.X + end.X) * 0.5, (start.Y + end.Y) * 0.5), FRotator(0, 90, 90), spawnInfo);
mapObject->meshMaterial = roadMaterial;
mapObject->staticMesh = staticMesh;
cMapObjects.Add(mapObject);
mapObject->SetActorRotation(FQuat(FRotator(angleToNextPoint, 90, 90)));
mapObject->SetActorScale3D(FVector3d(lengthBetween, thickness, thickness));
mapObject->Init();
};
void AGeoMap::ClearMapCache() {
for (auto mapObject : cMapObjects) {
float dist = FVector::Distance(mapObject->GetActorLocation(), FVector(0, cPlayerPos.X, cPlayerPos.Y)) / (mapSize*mapSize);
if (dist > renderDistance) {
mapObject->Destroy();
cMapObjects.Remove(mapObject);
}
}
}
long double AGeoMap::CalculateWorldDistance(long double lat1, long double lon1, long double lat2, long double lon2) {
// haversine formula
double dLat = FMath::DegreesToRadians(lat2 - lat1);
double dLon = FMath::DegreesToRadians(lon2 - lon1);
lat1 = FMath::DegreesToRadians(lat1);
lat2 = FMath::DegreesToRadians(lat2);
long double a = FMath::Pow(FMath::Sin(dLat * 0.5), 2) + FMath::Pow(FMath::Sin(dLon * 0.5), 2) * FMath::Cos(lat1) * FMath::Cos(lat2);
long double rad = 1;
long double c = 2 * FMath::Asin(FMath::Sqrt(a));
return rad * c;
}
