tl;dr: Given arbitrary SVG <path> how can I adjust the path commands to set a new origin for the file?
Details
I'm using Adobe Illustrator to create vector graphics for use in Android. Illustrator has a bug where under (unknown) circumstances the viewBox and all coordinates created for your graphics do not match the coordinates you set for the canvas and objects in Illustrator. Instead of (for example) viewBox="-7 0 14 20" you might get viewBox="-53 75 14 20". Usually the the path commands will be translated to fit inside that viewBox. Sometimes even that fails.
In a normal SVG file (a) this would rarely even be noticeable, and (b) it would be easy to fix by wrapping everything in a root-level <g transform="translate(46,-75)">. In an Android VectorDrawable this requires an extra <group> that I don't want to add, and (unlike SVG) I can't add a translate to the <path> itself. And in my code, the origin matters.
How can I adjust the path commands for all the paths in an SVG file to offset them by a fixed amount, allowing me to place the origin where I'd like?
A solution is to add explicit transform="translate(…,…)" onto each path that you want to adjust, view the SVG in a web browser, use the code in this question [note: my own] to bake the translate into the path data, and then use the Web inspector to get the changed values. Cumbersome.
Better: I've created a little online tool SVG Reoriginizer [no ads, no revenue] that lets you paste SVG code into the top box, click (or use alt+shift+arrow keys) to adjust the origin, and see the translated path commands shown in the bottom.
The core code is this function, which offsets the viewBox and all absolute path commands by the specified amount, and returns the changed SVG as a string:
function offsetOrigin(svg,dx,dy){
svg.viewBox.baseVal.x -= dx;
svg.viewBox.baseVal.y -= dy;
[].forEach.call(svg.querySelectorAll('path'),function(path){
var segs = path.pathSegList;
for (var i=segs.numberOfItems;i--;){
var seg=segs.getItem(i), c=seg.pathSegTypeAsLetter;
if (/[MLHVCSQTA]/.test(c)){
if ('x' in seg) seg.x -=dx;
if ('y' in seg) seg.y -=dy;
if ('x1' in seg) seg.x1-=dx;
if ('x2' in seg) seg.x2-=dx;
if ('y1' in seg) seg.y1-=dy;
if ('y2' in seg) seg.y2-=dy;
}
}
});
return (new XMLSerializer).serializeToString(svg);
}
Related
I have a webservice that returns GeoJson polygons (timezones) and I'm trying to draw them in a layer over the map object using GeoJsonLayer
I already tested the GeoJson file in geojson.io and it looks fine (image at the bottom) but when I add it to the map its not being filled and some extra lines appear down south, it looks like its not closing the poly properly, this is the code I'm using to load the file (I have it locally in raw folder at the moment)
val layer = GeoJsonLayer(mGoogleMap, R.raw.sample_timezones_response, requireContext())
layer.addLayerToMap()
val polygonStyle = GeoJsonPolygonStyle()
polygonStyle.fillColor = resources.getColor(R.color.color_main_green_200, null)
polygonStyle.zIndex = 10000f
layer.features.forEach { it1 ->
it1.polygonStyle = polygonStyle
}
This is the json file I'm trying with.
EDIT: the original json file was not followinf the right-hand rule, I fixed it with python lib: geojson-rewind, this is the fixed version that passes the test in https://geojsonlint.com/
I tried also updating to the latest version of the library (18.0.2) and updating the renderer to the newer one but it displays in the same way.
This is how it looks on android:
This is how its supose to look, same json file in geojson.io:
When validating the geojson, I get the error:
Line 1: Polygons and MultiPolygons should follow the right-hand rule
https://www.rfc-editor.org/rfc/rfc7946#section-3.1.6
A linear ring MUST follow the right-hand rule with respect to the
area it bounds, i.e., exterior rings are counterclockwise, and
holes are clockwise.
I created a multi-device firemonkey form which included one viewport3d ,one Cube and one camera.I want to make a calloutpanel exactly on the top of the cube in the form with camera projection.
In Firemonkey, we can use worldtoscreen() to convert absolute position properties to screen position. The resulting point is correct for the Windows platform but unfortunately in Android platform the point is not accurate.
Procedure TForm50.Cube1Render(Sender: TObject; Context: TContext3D);
var p:TPoint3D;
x,y:real;
Begin
p:=context.worldtoscreen(TProjection.Camera, Cube1.AbsolutePosition);
Label1.Text:=(p.x.tostring+' '+P.Y.ToString);
x:=p.X-(CalloutPanel1.Width /2);
y:=p.y-CalloutPanel1.Height;
CalloutPanel1.Position.X:=x;
CalloutPanel1.Position.y:=y;
End;
update
Base of this post WorldToScreen function C# my Cube1.AbsolutePosition must change base on size of monitor(android screen) to place CalloutPanel1 over cube1.
Who can apply this code on Delphi?
I am new to ARToolkit and I try to use the ARMovieProj from the examples (Android Studio Projects).
https://github.com/artoolkit/artoolkit5/tree/master/AndroidStudioProjects/ARMovieProj
I am able to change the NFT marker in the marker.dat
# Number of markers
1
# Entries for each marker. Format is:
#
# Name of pattern file (relative to this file)
# Marker type (SINGLE)
# Marker width in millimetres (floating point number)
# Optional tokens:
# FILTER [x] Enable pose estimate filtering for the preceding marker
# x (optional) specifies the cutoff frequency. Default
# value is AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT, which
# at time of writing, equals 5.0.
# A blank line
../DataNFT/markerkanji
NFT
FILTER 15.0
also the video displayed in the ARMovieActivity
private static final String movieFile = "Data/myvideo.mp4";
But the problem is the size of the video when it appears on screen. It's too small.
screenshot
I tried changing all the sizes I saw in the project but I am unable to enlarge the video. I can't find a solution online either.
The video itself is 1280*720.
Does someone knows how to do?
Actually the video is projected using perspective projection theory. That means it creates a matrix that is used for projection of video on marker. So, all you have to do is find the line in the code where the scale factor is used, like in the below code snippet.
Filename : ARMovie.cpp
// We have a new pose, so set that.
arglCameraViewRHf(markersNFT[i].trans, markersNFT[i].pose.T, 0.25f /*VIEW_SCALEFACTOR*/);
// Tell any dependent objects about the update.
//ARMarkerUpdatedPoseNotification
All you have to do is change the last arg of this function call according to your need i.e. (0.25f /VIEW_SCALEFACTOR/) and build the jni part.
I'm using the Corona sdk to create a simple Android game. I have it almost completely done, just trying to polish now. This is something that I'm having trouble with:
This is my game's setup page. Players are able to tap the up/down arrows to increase/decrease game attributes. I want the arrows to align with the numbers. My current code does not account for this:
local numPlayerstxt = display.newText("Number of players: "..NUMPLAYERS, w/2,7*h/20,0,0,"Quattrocento-Regular",24)
numPlayerstxt:setFillColor(0,0,0)
sceneGroup:insert(numPlayerstxt)
local numMafiatxt = display.newText("Number of Mafia: "..MAFIA, w/2,12*h/20,0,0,"Quattrocento-Regular",24)
numMafiatxt:setFillColor(0,0,0)
sceneGroup:insert(numMafiatxt)
local upTotal = display.newImage( "arrow1.png")
upTotal:translate(33*w/40, 6*h/20)
upTotal:scale(0.08, 0.08)
sceneGroup:insert(upTotal)
upTotal:addEventListener("tap", increasePlayers)
local downTotal = display.newImage( "arrow1.png")
downTotal:translate(33*w/40, 8*h/20)
downTotal:scale(0.08, 0.08)
downTotal.rotation = 180
sceneGroup:insert(downTotal)
downTotal:addEventListener("tap", decreasePlayers)
local upMafia = display.newImage( "arrow1.png")
upMafia:translate(32*w/40, 11*h/20)
upMafia:scale(0.08, 0.08)
sceneGroup:insert(upMafia)
upMafia:addEventListener("tap", increaseMafia)
local downMafia = display.newImage( "arrow1.png")
downMafia:translate(32*w/40, 13*h/20)
downMafia:scale(0.08, 0.08)
downMafia.rotation = 180
sceneGroup:insert(downMafia)
downMafia:addEventListener("tap", decreaseMafia)
As you can see, my code currently only takes into account screen width and height values in order to reasonably estimate the approximate locations. Inevitably this code fails to create any illusion of polish when the app is tried on different device screens.
Any suggestions on what I might do to align the arrows with the numbers? For instance, is there a way in Corona to find the end point of a textview, and align it in that way?
Thanks for reading.
try changing the anchorX of each arrows like this:
-- suppose one of your arrows is upArrow
upArrow.anchorX = 0.4 -- even try each float between 0 - 1
this move your object's anchor in x axis of the object.
I have a DrawingImage library (icons) for my Windows application development under WPF. I am new to Android development and this library has a lot of path geometries that I would like to use in my Android projects.
I searched to find a built-in way to use geometries such as "F1 M 0 0 -5.715 5 -8.48 5 -14.195 0 0 0 z m -15.0977 9.0001 0 -1 0 -7.461 5.488 4.803 -4.809 3.206 7.319 5.91 7.324 -5.91 -4.81 -3.206 5.488 -4.803 0 8.461 -7.998 6.795 -8.002 -6.795 z" directly in Android however I could not find a way.
I have run into some libraries that can display SVG images and they are OK. However I need to display my path geometries from XAML in android. Is this possible?
I found out that it is not possible to transfer my XAML vectors into Android environment. I took another way:
As far as I see, the best way to use verctor icons in Android is using font icon libraries. https://github.com/bperin/FontAwesomeAndroid is what I used.
Later I needed more icons than provided by the FontAwesome library. My search ended with http://fontastic.me/ service. You can generate your custom font collection free of charge. Then I modified source code of FontAwesomeAndroid so I am able to use my own font icon collection.