How to draw Polyline without rendering map using coordinates - react-native

I have array of coordinates and I can draw polyline on map using theese coordinates without problem.
Now what I want to do is, only drawing a polyline to screen without rendering the map.
Below is first few items of my coordinates array:
[
[6.56674, 45.39881],
[6.56682, 45.399],
[6.56701, 45.39959],
[6.56727, 45.40006],
[6.56738, 45.4003],
[6.56745, 45.40041],
[6.56757, 45.40053]
]
I want to draw the same polyline to black background without rendering map.
I tried to draw svg polyline using the array of coordinates but I couldn't achieved what I wanted only a dot appeared on the screen. Didn't draw a polyline.
import {Svg, Polyline} from 'react-native-svg';
<Svg height="100" width="100">
<Polyline
points={MY_ARRAY_OF_COORDS.map(item => `${item[0]},${item[1]`).join(" ")}
fill="none"
stroke="blue"
strokeWidth="5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>

The <polyline> is actually rendered but almost invisible since the coordinates are very close to each other.
So you need to calculate a scale factor.
Js example
const coords= [
[6.56674, 45.39881],
[6.56682, 45.399],
[6.56701, 45.39959],
[6.56727, 45.40006],
[6.56738, 45.4003],
[6.56745, 45.40041],
[6.56757, 45.40053]
];
//calculate coordinate range for a scale factor
let xArr = coords.map((val)=>{return val[0]} );
let xMin = Math.min(...xArr);
let xMax = Math.max(...xArr);
let yArr = coords.map((val)=>{return val[1]} );
let yMin = Math.min(...yArr);
let yMax = Math.max(...yArr);
let xRange = xMax- xMin;
let yRange = yMax- yMin;
let scale = 100/Math.max(...[xRange, yRange]);
//console.log(xRange, yRange, scale)
//scale coordinates
coords.forEach(function(coord){
let [x,y] =[coord[0], coord[1]];
coord[0] = (x-xMin)*scale;
coord[1] = (y-yMin)*scale;
})
//draw polyline
const svg = document.querySelector('svg');
const polyline = svg.querySelector('polyline');
polyline.setAttribute('points', coords.join());
svg{
border: 1px solid #ccc;
overflow:visible
}
<svg height="100" width="100">
<polyline
points=""
fill="none"
stroke="blue"
strokeWidth="10"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
First we need to calculate ranges for x and y values (so the maximum distances between maximum and minimum x).
let xRange = xMax- xMin; //0.000829999999999664
let yRange = yMax- yMin; //0.001720000000005939
If you need a svg bounding box of 100x100 units the scaling factor would be:
let scale = 100/Math.max(...[xRange, yRange]);
Eventually we need to subtract the minimum x and y offsets to align the polyline to the x/y axes origin.

Related

How to pixel perfect align text-element

I want my vue Konva Text element to completely fill the given height, like i expect of a rectangle.
This is issue becomes obvious when pairing with text images, (converting svg text to canvas) that properly match the given dimension
<v-text :config={
x: 50,
y: 50,
width: 1000,
height: 60,
fontSize: 60,
fontStyle: 'bold',
fontFamily 'Campton Book'
text: 'WELT'
}
/>
<v-rect
:config="{ x: 50, y: 50, fill: 'black', height: 60, width: 200 }"
/>
Second Part, is there any way to always pixel perfectly align the left side with the border? the x coordinate matches the border
Is this due to font constraints? What am I missing?
I tried to get the height of the text node to fix this positioning but this is the given height passed down as props
Text is defined as having parts above and below the baseline. Above is termed 'ascenders' amd below is 'descenders', which are required for lower case letters like j y g.
Setting the text fontSize to 60 does not say 'whatever the string, make it fill a space 60px high'. Instead it says 'Make text in a 60px font', which makes space for the descenders because they will generally be required.
If you know for sure that the text will be all caps, then a solution is to measure the height used and increase the font size by a computed factor so that the font fills the line height.
To do this you'll need to get the glyph measurements as follows:
const lineHeight = 60; // following your code
// make your text shape here...left out for brevity
const metrics = ctx.measureText('YOUR CAPS TEXT');
capsHeight = Math.abs(metrics.actualBoundingBoxAscent)
fontSize = lineHeight * lineHeight / capsHeight;
If I got that right, your 60px case should give a value around 75. That's based on the convention that ascenders are 80% of the line height. Now you set the font size of your shape to this new value and you should be filling the entire line height.
Regarding the left-alignment, this relies on what the font gurus call the a-b-c widths. The left gap is the a-space, the b is the character width (where the ink falls) and the c-space is the same as the a-space but on the right hand side.
Sadly unless someone else can tell me I am wrong, you don't get a-b-c widths in the canvas TextMetric. There is a workaround which is rather convoluted but viable. You would draw the text in black on an off-screen canvas filled with a transparent background. Then get the canvas pixel data and walk horizontal lines from the left of the canvas inspecting pixels and looking for the first colored pixel. Once you find it you have the measurement to offset the text shape horizontally.

How do I create a 10x10 grid for polygons<1 kilometer in turf.js?

How do I create a 10x10 grid for polygons<1 kilometer in turf.js?
let gridOptions = {units: 'kilometers'};
let grid = turf.squareGrid([ 176.4218616, -37.8028137, 176.4288378, -37.7992033 ], 100, gridOptions);
This produces an empty result. I presume because the polygon is too small.
That's right: your area is less than 1sqkm:
const area_in_sqkm = turf.convertArea(
turf.area(
turf.bboxPolygon([176.4218616, -37.8028137, 176.4288378, -37.7992033])
),
'meters', 'kilometers'
)
// area_in_sqkm = 0.2466
The units are applied to the cellSide argument when calling squareGrid. In your example your cellSide value is 100 meaning a grid with cells of size 100kmĀ². Change this value to resize the cells:
let grid = turf.squareGrid(bbox, 0.1, { units: 'kilometers'})

Can you change the bounds of a Sampler in a Metal Shader?

In the fragment function of a Metal Shader file, is there a way to redefine the "bounds" of the texture with respect to what the sample will consider it's normalized coordinates to be?
By default, a value of 0,0 for the sample is the top-left "pixel" and 1,1 is the bottom right "pixel" of the texture. However, I'm re-using textures for drawing and at any given render pass there's only a portion of the texture that contains the relevant data.
For example, in a texture of width: 500 and height: 500, I might have only copied data into the region of 0,0,250,250. In my fragment function, I'd like the sampler to interpret a normalized coordinate of 1.0 to be 250 and not 500. Is that possible?
I realize I can just change the sampler to use pixel addressing, but that comes with a few restrictions as noted in the Metal Shader Specification.
No, but if you know the region you want to sample from, it's quite easy to do a little math in the shader to fix up your sampling coordinates. This is used often with texture atlases.
Suppose you have an image that's 500x500 and you want to sample the bottom-right 125x125 region (just to make things more interesting). You could pass this sampling region in as a float4, storing the bounds as (left, top, width, height) in the xyzw components. In this case, the bounds would be (375, 375, 125, 125). Your incoming texture coordinates are "normalized" with respect to this square. The shader simply scales and biases these coordinates into texel coordinates, then normalizes them to the dimensions of the whole texture:
fragment float4 fragment_main(FragmentParams in [[stage_in]],
texture2d<float, access::sample> tex2d [[texture(0)]],
sampler sampler2d [[sampler(0)]],
// ...
constant float4 &spriteBounds [[buffer(0)]])
{
// original coordinates, normalized with respect to subimage
float2 texCoords = in.texCoords;
// texture dimensions
float2 texSize = float2(tex2d.get_width(), tex2d.get_height());
// adjusted texture coordinates, normalized with respect to full texture
texCoords = (texCoords * spriteBounds.zw + spriteBounds.xy) / texSize;
// sample color at modified coordinates
float4 color = tex2d.sample(sampler2d, texCoords);
// ...
}

The code/command to determine/change the length/height ratio of scale bar?

I would like to adjust the length/height ratio of the scale bar in an image by the DM scripting. As the following code shown, I can adjust the font size by changing "scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)", but I do not know how to change the shape (length/height ratio) of rectangle which constitute to the scale bar. Is there any code/command can achieve this? Thanks,
image front:=getfrontimage()
imagedisplay imgdisp=front.imagegetimagedisplay(0)
number nobar=imgdisp.componentcountchildrenoftype(31)
number fontsize=20
imgdisp.applydatabar(0)
component scalebar=imgdisp.componentgetnthchildoftype(31,0)
scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)
scalebar.componentsetdrawingmode(1)
When you select a scalebar, you will notice the green points showing that component's rectangle.
You control that rectangle like you control any component rectangle:
number kScaleBar = 31
image img := GetFrontImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
component scaleBar = disp.ComponentGetNthChildOfType( kScaleBar, 0 )
number t,l,b,r
scaleBar.ComponentGetRect(t,l,b,r)
Result("\n Current rect: [" + t + "/" + l + "/" + b + "/" + r )
number sx, sy
img.GetSize( sx, sy )
// Set centered half at bottom
l = sx*1/4
r = sx*3/4
t = sy*17/20
b = sy*19/20
scaleBar.ComponentSetRect(t,l,b,r)
Note, that you can not explicitly specify the length of the scalebar, it will always "snap" to a meaningful fraction within the boundary box, depending on the image calibration.
Setting the bounding rect will also override the font-size, while setting the font-size will override the boundary rect's height.

Calculte new width and height of the video based on the original width, height and ratio

After searching through - I wasn't able to find the answer so I'll give it a shot here.
I need to resize desktop video in order to feet it on mobile screen, let's say original width of the video was 1915 and original height was 1075, I calculated aspect ratio:
aspectRatio = (width/height); aspectRatio = 1.78;
Now my mobile screen resolution is: height = 1609, width = 1080.
How can I properly resize my video in order to keep the same aspect ratio??
Thank you
aspectRatio = (width/height)
You always want aspectRatio to be 1.78, if you want to prevent stretching or cropping.
And, the max new height is 1609 and the max new width is 1080, so:
1.78 = (1080/height)
height = 1080/1.78 = 606.74...
OR
1.78 = (width/1609)
width = 1.78*1609 = 2864.02...
So, you can have 1080x606.74 (which fits on screen), or 2864.02x1609 (which doesn't fit).
So, your answer is 1080x606.74...
Let's original dimensions are Wo, Ho, and target screen dimensions are Wt, Ht.
Rectangle with predetermined aspect will fit vertically if ratio of target and initial heights less than ratio of its widths, and will fit horizontally otherwise:
Coeff = Min(Wt/Wo, Ht/Ho)
W_Result = Wo * Coeff
H_Result = Ho * Coeff
or
if (Wt * Ho < Ht * Wo) then
W_Result = Wt
H_Result = Ho * Wt / Wo
else
W_Result = Wo * Ht / Ho
H_Result = Ht