How can I programatically detect overlap of SVG elements? - svg

I want to programatically create time lines similar to this:
source
Each event will be at a vertical position determined by its datetime, but it can have arbitrary-length text, and must be positioned vertically so that it doesn't overlap with another event box.
How can I programatically detect overlap of SVG elements so that I can move them up or down as needed? A solution in any programming language or using any library is fine, but ideally I'd like to build this time line without involving a browser; I want this to be a command-line utility.
(I think this is possible because GraphViz Dot can output undirected graphs as SVG and keeps the nodes from overlapping - see the Wikipedia article.)

Related

How can I adjust a GraphViz render

I'm trying to render a tree that is very broad... and it renders, as expected, in a long, skinny horizontal image.
Problem is that I need a graph suitable for a document. I would very much like to take and move the nodes that are rendered horizontally and "drag" them down so that the graph is more vertical... with the edges curving to accommodate this. Are there any clever ways to accomplish this? GraphViz settings? Third party tools that let me manipulate and fine tune the output? I work mostly in the Python ecosystem, but open to others. Also open to the use of tools like Visio and other pro drawing tools. Thanks!
Edit
After implementing the answer below by #sroush, and then tweaking a little further with Photoshop, got some nice results.
Tweaking the above in Photosop. Had to add the two curved edges after the secondary node by hand, but it's worth it. Much more presentable.
I assume you are using dot, and your graph "naturally" has only a few ranks (rows).
There are a few tweaks that will help a bit (reducing node horizontal footprints):
node [shape=rect] // snugger fit into rectangles
insert newlines into node labels e.g. xxx [label="Controller Board\n#19_8"])
Also try the unflatten program (https://www.graphviz.org/pdf/unflatten.1.pdf). It will increase the apparent number of ranks (rows).
See related question here with command line examples:
Distribute nodes on the same rank of a wide graph to different lines
You can use the minlen property to limit the minimum level span of some edges.This avoids the result becoming very long in the horizontal position.
For example:
digraph {
a->b
a->c
a->d
a->e
}
This will output the following image:
But when minlen is used, the picture will become longer vertically but shortened horizontally:
digraph {
a->b
a->c
a->d[minlen=2]
a->e[minlen=3]
}

What's the differences with the line, path, and shape classes in KonvaJS?

I'm a big fan of PaperJS, however, the library doesn't see much activity so we're looking at other tools, like KonvaJS, Fabric, and Pixi. We'd like to replicate the example here:
http://paperjs.org/examples/path-simplification/
in KonvaJS but we're not sure which class is the most appropriate? Should we use the line, which is described as a collection of points with tension, the path tool which is what we use in Paper, or the shape class? Does KonvaJS offer the same type of access to the bezier curve tools and shape border, blue line, found in the above-mentioned paper example?
Konva.Line requires a list of x & y passed into its points property as a simple array, then draws straight lines connecting those points. The tension property can be used to make the straight line joins more curvy.
Konva.Path expects you to provide a data property that is more like a list of SVG drawing instructions, so move, lineto, arc, etc. (See supported instructions list in Konva docs for Konva.Path.data here)
There is no built-in equivalent path-editing features to those in the demo you linked to - so no automatic anchors on the path control points and no Bezier handles. You would have to DIY those. Having said that, it would all be achievable - what I mean is the drawing of the control anchors and lines, the listening for mouse and drag events, and the final passing back of the SVG drawing data to the Konva.Path shape when the path's edit mode ends are all well supported in Konva.
As at May 2022, the Konva lib is well supported, with appropriately frequent (as Goldilocks would want - not too many and not too few), no ill-thought-out breaking changes, issues are responded to, SO posts replied to, and there is a busy Discord channel.

gimp text on a dial placed at specific locations (degrees)

I have a (circular) dial. I would like to place text centered at a specific angle on the dial. A simple analogy would be a clock face with text above each hour mark. I can write text along an arc, placing text at the top (12h) position, then rotate that path to place it at a specific angle. The only solution I could think of was to create 1 layer for each text then rotate that layer appropriately (10 deg, 20 deg, 30 deg, etc.). This seems a brute force method, and I have not even been able to get it to work (yet). So, is there a better, standard way to do this?
TIA
ken
Definitely no standard way. But there are scripts that can make that easier. They can be found here (some come with a self-contained doc, go directly to the download page.
dial-marks will generate marks (with round sides if required). It's easy to remove the excess point to keep only arcs. You can have other uses for that one if you are in clocks.
ofn-path-edit (break apart function) is used to make one path per stroke
text-along-path can then be used to add text (centered) on each of these paths.
Results of the three main steps
If you want to script this, plenty of code to borrow from in these scripts.

Point in Polygon check with SVG and JavaScript?

I have a map that I converted from a raster graphic into an SVG file by converting the differently coloured areas into paths.
I know how to do a basic point-in-polygon check given an array of edges, but the svg:path elements represent multiple polygons as well as masks (to account for seas etc) and extracting that information by parsing the d attribute seems rather heavy-handed.
Is there a JS library that allows me to simplify that check? I basically want to create random points and then check whether they are on land (i.e. inside the polygons) or water (i.e. outside).
As SVG elements seem to allow for mouse event handling, I would think that this shouldn't be much of a problem (i.e. if you can tell whether the mouse pointer is on top of an element, you are already solving the point-in-polygon problem).
EDIT: Complicating the matter a bit, I should mention that the svg:path elements seem to be based on curves rather than lines, so just parsing the d attribute to create an array of edges doesn't seem to be an option.
As the elements can take a fill attribute, a ghetto approach of rendering the SVG on a canvas and then finding the colour value of the pixel at the given point could work, but that seems like a really, really awful way to do it.
The answers on Hit-testing SVG shapes? may help you in this quest. There are issues with missing browser support, but you could perhaps use svgroot.checkIntersection to hit test a small (perhaps even 0 width/height would work?) rectangle within your polygon shape.
The approach I suggested as a last resort seems to be the easiest solution for this problem.
I found a nice JS library that makes it easy to render SVG on a canvas. With the SVG rendered, all it takes is a call to the 2D context's getImageData method for a 1x1 region at the point you want to check. I guess it helps to create a copy of the SVG with colour coding to make the check easier if your SVG is more complex than the one I'm using (you'll have to check the RGBA value byte-by-byte).
This feels terribly hackish as you're actually inspecting the pixels of a raster image, but the performance seems to be decent enough and the colour checks can be written in a way that allows for impurities (e.g. near the edges).
I guess if you want relative coordinates you could try creating a 1-to-1 sized canvas and then divide the pixel coordinates by the canvas dimensions.
If somebody comes up with a better answer, I'll accept it instead. Until then, this one serves as a placeholder in case someone comes here with the same problem looking for an easy solution.

Modifying a model and texture mid-game code

Just have a question for anyone out there who knows some sort of game engine pretty well. What I am trying to implement is some sort of script or code that will allow me to make a custom game character and textures mid-game. A few examples would be along the lines of changing facial expressions and body part positions in the game SecondLife. I don't really need a particular language, feel free to use your favorite, I'm just really looking for an example on how to go about this.
Also I was wondering if there is anyway to combine textures for optimization; for example if i wanted to add a tattoo to a character midgame, is there any code that could combine his body texture and the tattoo texture into one texture to use (this way I can simply just render one texture per body.)
Any tips would be appreciated, sorry if the question is a wee bit to vauge.
I think that "swappable tattoos" are typically done as a second render pass of the polygons. You could do some research into "detail maps" and see if they provide what you're looking for.
As for actually modifying the texture data at runtime, all you need to do is composite the textures into a new one. You could even use the rendering API to do it for you, more than likely; render the textures you want to combine in the order you want to combine them into a new texture. Mind, doing this every frame would be a disoptimization since it'll be slower to render two textures into one and then draw the new one than it would be just to draw the two sources one after the other.

Resources