Line hidden under shape

I create a lot of wiring layout diagrams. Not schematics. Lines are wires, squares or circles (filled) are terminal points.

I want the wires to connect to the centers of the terminals (shapes), not the edges. So, I check “Allow Route From Object Centers”. The only problem is that the shape hides the line, as if the shape ordering was “bring to front”. This makes it appear that the line is still connecting to the edge, not the center.

I’m currently working around this by manually adding a magnet to the center of each terminal shape, and turning OFF “Route From Object Centers”.

How can I make the line appear over the filled shape, all the way to the center point?

Thanks.

Round From Object Centers on, then select the line and choose Order>Bring to Front. I think the stacking order is what controls which item draws on top, so alternately you can select the item you want and send it to the back. That is assuming your lines and shapes are on the same layer.

Hope this helps!

Lanette

All on the same layer, but this doesn’t help. Try it!

Without an example is it hard to tell what could be going wrong. Please choose Contact Omni from the help menu and include a simple example. If you are working on something confidential, you can use the “make anonymous” checkbox which will replace your text with “x”.

Thanks,
Lanette

1 Like

Example sent.

I think the stacking order is what controls which item draws on top

Not, I believe, in the case of shape ⇄ link relationships. Changing the stacking order can’t bring the hidden part of centre to centre links into view.

What I would probably do, manually or scripted, is to convert the atomic shapes into (grouped) compound shapes, each with a tiny invisible mosbolletjie (tiny thingummy) above and at the centre of the main shape.

35

I made some wrong assumptions above, as the stacking order only works for lines that are not connected.

I wanted to share the right way to move where the line connects in case anyone else is looking for this:

  1. Turn off Route From Object Centers.
  2. Use the Magnet tool to place a custom magnet in the center.
  3. Route the line to the custom magnet.
2 Likes

Yes, that’s what I’ve been doing. But, FYI, I had forgotten to turn off route object centers in some cases. When I’d show magnets, I’d see my manually placed one. But when I’d try to attach a line, it would fight between the magnet, and the automatic center point. If the center point “won”, the line path would be obscured. Took me a while to figure that out, because I’m working on small objects, and didn’t realize there were two active connection points.

In summary: don’t forget to turn off route from center.

Thanks ! Much better.

57

A question (I have missed something) how do we set centre magnets through the GUI ?

08

at first sight I can only see edge magnet options, and I reached for a JXA script to set something in the middle, but there’s clearly some other route …

// JavaScript for Automation (JXA) script for Script Editor
(() => {
    'use strict';

    // GENERIC FUNCTIONS -----------------------------------------------------

    // bindMay (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
    const bindMay = (mb, mf) =>
        mb.nothing ? mb : mf(mb.just);

    // just :: a -> Just a
    const just = x => ({
        nothing: false,
        just: x
    });

    // nothing :: () -> Nothing
    const nothing = (optionalMsg) => ({
        nothing: true,
        msg: optionalMsg
    });

    // JXA FUNCTION ----------------------------------------------------------

    // windowMay :: Application -> Maybe Window
    const windowMay = app =>
        app.documents.length > 0 ? (
            just(app.windows.at(0))
        ) : nothing('No windows open');

    // OMNIGRAFFLE FUNCTIONS -------------------------------------------------

    // graphicMay :: OmniGraffle Window -> Maybe Graphic
    const graphicMay = win =>
        win.selection()
        .length > 0 ? (
            just(win.selection()[0])
        ) : nothing('Nothing selected');

    // centerMagnetMay :: Shape -> Maybe [Magnet]
    const centerMagnetMay = shape =>
        (shape.magnets = [
            [0, 0]
        ], just(shape.magnets()));


    // MAIN ------------------------------------------------------------------
    return bindMay(
        bindMay(
            windowMay(Application('OmniGraffle')),
            graphicMay
        ),
        centerMagnetMay
    );
})();

I’d like to know that, too. Currently, I just eyeball it.

1 Like

For g1 being the graphic, I’m seeing this add a center magnet (not sure why).

g1.magnets = [new Point(0.00, 0.00)];

It appears to me from a few tests that 0, 0 is the graphic center for adding a magnet, and you can move left and up with negative pixel values, and right and down from there with positive pixel values to add magnets.

1 Like

g1.magnets = [new Point(0.00, 0.00)];

That’s omniJS (my script above is JXA)

Probably worth making sure that people know where to execute them :-)

JXA -> Script Editor
omniJS -> Automation Console

The [0,0] is the origin of the shape.

The unit is the shape width / 2.
Edge magnets are placed at positions expressed as cartesian coordinates (unit 1) away from the centre.

NSEW

[[0,1],[0,-1],[1,0],[-1,0]]

NS

[[0,1],[0,-1]]

EW

[[1,0],[-1,0]]

etc

(and of course the N magnets per vertex placements are a bit less readable.

For example, two magnets per side (on a square):

41

[[-0.42163702135578357,-1],[0.42163702135578357,-1],
[1,-0.42163702135578357],[1,0.42163702135578457],
[0.42163702135578357,1],[-0.42163702135578357,1],
[-1,0.42163702135578457],[-1,-0.42163702135578457]]

An OmniJS version for OG 7.5 and iOS OG 3 Automation > Show Console etc

(For selected graphics, set a single central magnet for each graphic).

(() => {
    // NB
    //  OmniJS for OmniGraffle 7.5 (Not JXA for Script Editor)
    //  Test in OG > Automation > Show Console

    // Magnets of all selected graphics set to
    // a single magnet at the centre of the graphic.

    const
        pointOrigin = new Point(0.00, 0.00),
        lstMagnets = [pointOrigin];

    return document.windows[0].selection.graphics
        .map(g => (
            // Effect
            g.magnets = lstMagnets,
            // Return value
            g.magnets
        ));
})();
1 Like

Even with omniJS scripts it can (on macOS) be easier to launch them from JavaScript for Automation, using Script Menu, Keyboard Maestro, FastScripts etc. Here is a way of wrapping an omniJS function in a JXA script, and running it in macOS OmniGraffle.

For iOS OmniGraffle 3, you could launch the same setMagnetsForSelections function with an argument from iOS apps with JavaScript interpreters, like 1Writer and Drafts, or from WorkFlow, but you wouldn’t use this JXA wrapper. The runOmniJSinOmniGraffle function is macOS-only.

(() => {

    ObjC.import('AppKit');

    // This is a JXA script, which can be run from Keyboard Maestro,
    // FastScript, Script Menu etc.
    // The function  setMagnetsForSelections is an omniJS function,
    // which is launched by URL-encoding it and then opening
    // a 'omnigraffle:///omnijs-run?script=' URL with it.

    // Sample arguments for this function:

    // One central magnet :: [[0, 0]]
    // North South :: [[0,1],[0,-1]]
    // East West :: [[1,0],[-1,0]]
    // NSEW :: [[0,1],[0,-1],[1,0],[-1,0]]


    // setMagnetsForSelections :: [(Int, Int)] -> OmniGraffle IO ()
    const setMagnetsForSelections = xys => {
        const lstMagnets = xys.map(([x, y]) => new Point(x, y));
        return document.windows[0].selection
            .graphics
            .map(g => (
                // Effect
                g.magnets = lstMagnets,
                // Return value
                g.magnets
            ));
    };

    // omniJS Function -> Arguments -> Bool

    // runOmniJSinOmniGraffle :: omniJS Function -> a -> Bool
    const runOmniJSinOmniGraffle = (f, args) =>
        $.NSWorkspace.sharedWorkspace.openURL(
            $.NSURL.URLWithString(
                'omnigraffle:///omnijs-run?script=' +
                encodeURIComponent(
                    '(' + f + ')(' + JSON.stringify(args) + ')'
                )
            )
        );

    // MAIN ------------------------------------------------------------------
    runOmniJSinOmniGraffle(
        setMagnetsForSelections,
        [[0, 0]]  // Single central magnet
    );
})();