How to use MKMapKit to generate polyline for Continental United States Boundary? - mkmapview

Note: If this question requires more information, please add a comment.
Details:
I would like to generate a boundary line around the continental United States on an MKMapView. The idea is to begin drawing overlays on the area outside of the country outline (I need to de-emphasize external areas and just have the US be the primary focal point; I am considering a blur effect but would be open to suggestions on implementation or other methods to achieve the objective).
Background:
I need to blur out (or de-emphasize) the other countries that appear in the default MKMapView other than the Continental US.
My Initial Approach:
Identify the contiguous country boundary box using polylines
(similar to how a bus route is represented on the map; I note there
seems to be some default line ~ any method to access those
coordinates?)
Identify a method to mask the map using a UIVisualEffectView with
blur (or any other possibility to dim that portion of the map not
inside the boundary)
I don't necessarily need a code solution (though if posted, I'll try it). I am wondering if someone experienced in this area could provide pseudo code or just some pointers as to the best approach to take on this process.
Other Research:
I have reviewed other sources, including the MapKit documentation and this overlay tutorial.

You would need to draw a polygon around all your MKMapView with an inner polygon that would be the area you don't want to blur out.
Here is my solution:
First you need the coordinates to cover every bit of the map:
struct WorldCoordinates {
static let values = [
CLLocationCoordinate2D(latitude: 90, longitude: 0),
CLLocationCoordinate2D(latitude: 90, longitude: 180),
CLLocationCoordinate2D(latitude: -90, longitude: 180),
CLLocationCoordinate2D(latitude: -90, longitude: 0),
CLLocationCoordinate2D(latitude: -90, longitude: -180),
CLLocationCoordinate2D(latitude: 90, longitude: -180)
]
}
Then use a method like this one to add your inner and outer polygons:
Please note that I use "City" as an example of a struct with boundigCoordinatesArray being an array of the bounding coordinates of the area you don't want to blur.
func addCityBoundingPolygon(in mapView: MKMapView, with city: City) {
// Declare your inner polygon
let innerPolygon = MKPolygon(coordinates: city.boundingCoordinatesArray, count: city.boundingCoordinatesArray.count)
innerPolygon.title = "\(city.id)"
// Declare your outer polygon with previously created inner polygon
let outerPolygon = MKPolygon(coordinates: WorldCoordinates.values, count: WorldCoordinates.values.count, interiorPolygons: [innerPolygon])
mapView.addOverlay(outerPolygon)
}
Finally add the color of your outer polygon on your MKMapViewDelegate like this:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polygon = overlay as? MKPolygon {
let renderer = MKPolygonRenderer(polygon: polygon)
renderer.fillColor = UIColor.outOfCityBounds().withAlphaComponent(0.1)
renderer.strokeColor = UIColor.outOfCityBounds().withAlphaComponent(0.4)
renderer.lineWidth = 1
return renderer
}
return MKOverlayRenderer()
}
With this approach you will be able to recreate something like this:

Related

Three JS Phong Material not showing even with Ambient Light on Custom Mesh

Here I'm creating a lined object through forming a Mesh, then applying a MeshPhongMaterial.
Have set my scene, and created a mesh object where I apply the Phong Material to. However the material itself is not evident.
Is this potentially due to the way I'm creating vertices? Perhaps there is a complexity in the material (try adding wireframe to view complexity)
I have added scene and ambient lighting.
I've made a demo of this here. Here is a snippet of the material itself
const material = new THREE.MeshPhongMaterial({
color: 0xFF0000, // red (can also use a CSS color string here)
shininess: 150,
side: THREE.DoubleSide,
metalness: 0.5,
emissive: 'red'
});
That's because your geometry doesn't have normals, and PhongMaterial needs normals to calculate its color. Simply adding the default [0, 0, 1] normal in you xyzSet() function renders the red color you're expecting:
g.normals[ posIdx ] = 0;
g.normals[ posIdx + 1 ] = 0;
g.normals[ posIdx + 2 ] = 1.0;

SwiftUI: How to combine a Double with a String and do a math calculation?

I am still totally new to Swift / SwiftUI and coding in general.
I asked this question before but it was closed because it was apparently a duplicate, but (!) this does not account for SwiftUI and I cannot get this thing to work in SwiftUI, because even if I use the suggested NSExpression, I cannot use the result, because it is not a View and I have no idea on how to convert it to a View (see the update at bottom of the question).
I am trying to make a simple converter with a set of predefined conversion from a DataModel. So far I can populate the ContentView and move into a DetailView where I have created a slider which automatically updates a TextView whenever the slider is moved and the whole screen is populated through the DataModel (I hope I explain this the right way).
Now my problem is that every single conversion uses a different calculation obviously. For instance "/ 1000" or "* 50". I have stored these parts as Strings in the DataModel. Now what I'd like to do is to use these Strings in my calculation, but I have no idea how I can include them. Obviously I cannot convert these to Doubles to make a calculation. Here is the code and DataModel:
DataModel:
struct Converter: Identifiable {
var id = UUID()
var title: String
var range = 0.0...0.0
var calc: String
var sliderValue: Double
var color: [Color]
var description: String
}
As you can see "calc" is of type String. I am also using "range" which I defined with 0.0...0.0 because I didn't know how I could initialize it otherwise (I always got an error because of a closed range (?) so this is what I cam up with to silence the error.
Here is an example of some data:
let converterData: [Converter] = [
Converter(
title: "Conversion1",
range: 0.0...200,
calc: "/ 1000",
sliderValue: 0.0,
color: [Color.blue, Color.red],
description: "This is conversion 1"
),
...
...
As you can see I have changed the range to "0.0...200" because the slider shouldn't go beyond 200. I have entered the part of the calculation "/ 1000" into calc. This is the thing I'd like to add to the calculation in the DetailView (see below). I am not using the rest of the data right now, because I am still stuck with this calculation.
Code:
#State var sliderValue: Double = 0.0
var conversion: Converter
var body: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading) {
Text("value1".uppercased())
.font(.largeTitle)
.fontWeight(.bold)
Text("\(sliderValue, specifier: "%.2f")")
.font(.system(size: 60, weight: .bold))
Text("to value2".uppercased())
.font(.largeTitle)
.fontWeight(.bold)
self.calculatedView(for: sliderValue)
}
Slider(value: $sliderValue, in: conversion.range, step: 0.5)
.padding(8)
.overlay(
Capsule()
.stroke(Color.purple, style: StrokeStyle(lineWidth: 5))
)
}
.padding()
}
As you can see I use "conversion.range" to specify the exact range for the slider. Here is the calculation:
private func calculatedView(for value: Double) -> some View {
Text("\(value / 1000, specifier: "%.2f")")
.font(.system(size: 60, weight: .bold))
}
}
Update:
So what I did was to try to use NSExpression in calculatedView:
private func calculatedView(for value: Double) -> some View {
let calculation = String(value) + conversion.calc
let expn = NSExpression(format:calculation)
let result = expn.expressionValue(with: nil, context: nil)
Text(result)
.font(.system(size: 60, weight: .bold))
}
I am not even sure if this is the way to use NSExpression. I am trying to create a string from the value of the slider and add conversion.calc. It should look something like this: 125.5 / 1000 (just as an example). I am not sure if this is right in the first place.
Now I try to use NSExpression and store the result in the variable result and this variable should be shown as a TextView. I get two error messages:
Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
And for Text(result):
2. No exact matches in call to initializer
Question
Right now I just add the value and hard-code the "/ 1000" in. What I'd like to change is instead use converter.calc (which is "/ 1000). But obviously when I just add this the whole calculation is broken, but I have no idea how the re-format the whole thing so that it works. Before I would have just created a switch statement (or something else) with a new calculation for each conversion, which would blow up the whole code.
I really hope someone can point me into the right direction, because I am so happy that I have finally understood how to use a simple DataModel.
Thanks for reading and for any tip. With best regards!
Rather have the calc property in Converter hold a closure. This way you could pass in any sort of conversion function when initializing a Converter (by passing in a conversion closure). Perform all calculations in Double (as numbers) and then convert to String for displaying.
Here is a link to Closures at Swift.org
It's going to be a huge mess trying to perform maths with Strings and Numbers.
EDIT Simple example of using Closure
All else being the same except for the calc variable
struct Converter {
var calc: ((Double) -> Double)
}
Usage
let closure: ((Double) -> Double) = { num in
return num / 1000
}
let converter = Converter(calc: closure)
print("Conversion result: \(converter.calc(500))")
You could pass any sort of calculation method into the converter, or you could hard the method in the struct itself and just call calc which will auto grab any variables within the struct.
But for your issue instead of the CalculatedView function:
VStack(alignment: .leading) {
Text("value1".uppercased())
.font(.largeTitle)
.fontWeight(.bold)
Text("\(sliderValue, specifier: "%.2f")")
.font(.system(size: 60, weight: .bold))
Text("to value2".uppercased())
.font(.largeTitle)
.fontWeight(.bold)
Text("\(conversion.calc(sliderValue))")
.font(.system(size: 60, weight: .bold))
}

Camera controls are opposite to what they should be. Why?

I am creating a playable maze in Three.js. All the objects —the floor, the ceiling and the walls— have been placed within positive X and Z axises. The camera is placed like this:
camera = new THREE.PerspectiveCamera(45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, 0.25, 0);
// The camera is placed pointing to the nearest open path from the
// initial position. Check mazeGenerator.js for the reference of
// "coordinates".
if(grid[1][0] == coordinates.W)
{
camera.lookAt(new THREE.Vector3(1, 0.25, 0));
}
else
{
camera.lookAt(new THREE.Vector3(0, 0.25, 1));
}
and it moves like that:
function keyboardCheck()
{
var movementSpeed = 0.02;
var rotationSpeed = 0.03;
if(keyboard.pressed('w') || keyboard.pressed('up'))
{
camera.translateZ(-movementSpeed);
}
if(keyboard.pressed('a') || keyboard.pressed('left'))
{
camera.rotateY(rotationSpeed);
}
if(keyboard.pressed('d') || keyboard.pressed('right'))
{
camera.rotateY(-rotationSpeed);
}
}
If I place the camera without the lookAt function, it seems that it faces [0, 0, 0], but of course what I wanted to do was help the player a little bit by making the camera face the nearest open path possible.
In order to make it move forward, I have to decrement Z, because otherwise when you hit the "move forward" key it goes backwards. This makes me think that even though I am telling the camera to look at a certain direction, the object's Z axis is opposite to the world's Z axis.
The question itself is: why is this happening?
Thank you very much in advance.
https://github.com/MikelAlejoBR/3D-Maze-95/tree/0.4
https://github.com/MikelAlejoBR/3D-Maze-95/issues/8
The camera is looking down its negative-z axis, so to move forward, do this:
camera.translateZ( - distance );
All other objects are considered to be looking in the direction of their positive-z axis, so to move other objects forward, you would use
object.translateZ( distance );
three.js r.85

How to remove the effect of light / shadow on my model in XNA?

I am developing a small game and I would draw a field-ground(land) with a repeated texture. My problem is the rendered result. This gives the impression of seeing everything around my cube looked as if a light shadow.
Is it possible to standardize the light or remove the shadow effect in my drawing function?
Sorry for my bad english..
Here is a screenshot to better understand my problem.
Here my code draw function (instancing model with vertexbuffer)
// Draw Function (instancing model - vertexbuffer)
public void DrawModelHardwareInstancing(Model model,Texture2D texture, Matrix[] modelBones,
Matrix[] instances, Matrix view, Matrix projection)
{
if (instances.Length == 0)
return;
// If we have more instances than room in our vertex buffer, grow it to the neccessary size.
if ((instanceVertexBuffer == null) ||
(instances.Length > instanceVertexBuffer.VertexCount))
{
if (instanceVertexBuffer != null)
instanceVertexBuffer.Dispose();
instanceVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, instanceVertexDeclaration,
instances.Length, BufferUsage.WriteOnly);
}
// Transfer the latest instance transform matrices into the instanceVertexBuffer.
instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
Game.GraphicsDevice.SetVertexBuffers(
new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);
Game.GraphicsDevice.Indices = meshPart.IndexBuffer;
// Set up the instance rendering effect.
Effect effect = meshPart.Effect;
//effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];
effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
effect.Parameters["Texture"].SetValue(texture);
// Draw all the instance copies in a single call.
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
meshPart.NumVertices, meshPart.StartIndex,
meshPart.PrimitiveCount, instances.Length);
}
}
}
}
// ### END FUNCTION DrawModelHardwareInstancing
The problem is the cube mesh you are using. The normals are averaged, but I guess you want them to be orthogonal to the faces of the cubes.
You will have to use a total of 24 vertices (4 for each side) instead of 8 vertices. Each corner will have 3 vertices with the same position but different normals, one for each adjacent face:
If the FBX exporter cannot be configured to correctly export the normals simply create your own cube mesh:
var vertices = new VertexPositionNormalTexture[24];
// Initialize the vertices, set position and texture coordinates
// ...
// Set normals
// front face
vertices[0].Normal = new Vector3(1, 0, 0);
vertices[1].Normal = new Vector3(1, 0, 0);
vertices[2].Normal = new Vector3(1, 0, 0);
vertices[3].Normal = new Vector3(1, 0, 0);
// back face
vertices[4].Normal = new Vector3(-1, 0, 0);
vertices[5].Normal = new Vector3(-1, 0, 0);
vertices[6].Normal = new Vector3(-1, 0, 0);
vertices[7].Normal = new Vector3(-1, 0, 0);
// ...
It looks like you've got improperly calculated / no normals.
Look at this example, specifically part 3.
A normal is a vector that describes the direction that light would reflect off that vertex/poly if shined orthogonally to it.
I like this picture to demonstrate The blue lines are the normal direction at each particular point on the curve.
In XNA, you can calculate the normal of a polygon with vertices vert1,vert2,and vert3 like so:
Vector3 dir = Vector3.Cross(vert2 - vert1, vert3 - vert1);
Vector3 norm = Vector3.Normalize(dir);
In a lot of cases this is done automatically by modelling software so the calculation is unnecessary. You probably do need to perform that calculation if you're creating your cubes in code though.

Using ShowTextAtPoint the displayed text is flipped

I'm using the ShowTextAtPoint method of CGContext to display a Text in a view, but it is displayed in flip mode, anyone knows how to solve this problem ?
Here is the code I use :
ctx.SelectFont("Arial", 16f, CGTextEncoding.MacRoman);
ctx.SetRGBFillColor(0f, 0f, 1f, 1f);
ctx.SetTextDrawingMode(CGTextDrawingMode.Fill);
ctx.ShowTextAtPoint(centerX, centerY, text);
You can manipulate the current transformation matrix on the graphics context to flip it using ScaleCTM and TranslateCTM.
According to the Quartz 2D Programming Guide - Text:
In iOS, you must apply a transform to the current graphics context in order for the text to be oriented as shown in Figure 16-1. This transform inverts the y-axis and translates the origin point to the bottom of the screen. Listing 16-2 shows you how to apply such transformations in the drawRect: method of an iOS view. This method then calls the same MyDrawText method from Listing 16-1 to achieve the same results.
The way this looks in MonoTouch:
public void DrawText(string text, float x, float y)
{
// the incomming coordinates are origin top left
y = Bounds.Height-y;
// push context
CGContext c = UIGraphics.GetCurrentContext();
c.SaveState();
// This technique requires inversion of the screen coordinates
// for ShowTextAtPoint
c.TranslateCTM(0, Bounds.Height);
c.ScaleCTM(1,-1);
// for debug purposes, draw crosshairs at the proper location
DrawMarker(x,y);
// Set the font drawing parameters
c.SelectFont("Helvetica-Bold", 12.0f, CGTextEncoding.MacRoman);
c.SetTextDrawingMode(CGTextDrawingMode.Fill);
c.SetFillColor(1,1,1,1);
// Draw the text
c.ShowTextAtPoint( x, y, text );
// Restore context
c.RestoreState();
}
A small utility function to draw crosshairs at the desired point:
public void DrawMarker(float x, float y)
{
float SZ = 20;
CGContext c = UIGraphics.GetCurrentContext();
c.BeginPath();
c.AddLines( new [] { new PointF(x-SZ,y), new PointF(x+SZ,y) });
c.AddLines( new [] { new PointF(x,y-SZ), new PointF(x,y+SZ) });
c.StrokePath();
}

Resources