Draw a free line on layout

That depends on what Geometry you are making.

I don’t understand or maybe I am confused now.

I went according to your above comment, is there something still missing ? I just want to be able to draw a simple staright line on layout.

How are you initializing the new Geometry?

Here, makeGeo() and makeNewGeo() are the two methods I am using to intialize and modify the geometry respectively.


  drawLine() {
    const $ = go.GraphObject.make;
    const cxt = this;
    const fp: Floorplan = this.floorPlan;

    fp.nodeTemplateMap.add("ScaleLineNode", this.makeScaleLineNode());

    fp.toolManager.mouseMoveTools.insertAt(
      2,
      $(DragCreatingTool, {
        isEnabled: true, // disabled by the checkbox
        delay: 0, // always canStart(), so PanningTool never gets the chance to run
        archetypeNodeData: {
          stroke: "green",
          strokeWidth: 3,
          category: "ScaleLineNode",
          loc: new go.Point(0, 0),
          geo: this.makeGeo(),
        },
        insertPart(bounds) {
          const part = DragCreatingTool.prototype.insertPart.call(this, bounds);
          part.data.geo = cxt.makeNewGeo(this.diagram);
          const shape: go.Shape = part.findObject('SHAPE') as go.Shape;
          const pos = part.data.geo.copy();
          part.position.x = - pos.startX - shape.strokeWidth / 2;
          part.position.y = - pos.startY - shape.strokeWidth / 2;
          //part.position = pos;

          return part;
        }
      }));
  }

  makeGeo() {
    const data = new go.Geometry(go.Geometry.Line);

    data.startX = 0;
    data.startY = 0;
    data.endX = 1;
    data.endY = 1;

    return data;
  }

  makeNewGeo(diag) {
    const data = new go.Geometry(go.Geometry.Line);

    data.startX = diag.firstInput.documentPoint.x;
    data.startY = diag.firstInput.documentPoint.y;
    data.endX = diag.lastInput.documentPoint.x;
    data.endY = diag.lastInput.documentPoint.y;
    data.normalize();
    return data;
  }

So your makeGeo function always creates a line that goes from top-left to bottom right. Is that what you want?

You are not using the return value from Geometry.normalize to position the Node.

The value of Part.position is immutable. GraphObject | GoJS API

Tried to incorporate everything that you just said, still going nowhere. Can you help me with a sample or some code, I think I may not be understanding you correctly.

         archetypeNodeData: {
          stroke: "green",
          strokeWidth: 3,
          category: "ScaleLineNode",
          loc: new go.Point(0, 0),
          geo: this.makeGeo(fp)
        },
        insertPart(bounds) {
          const part = DragCreatingTool.prototype.insertPart.call(this, bounds);
          const shape: go.Shape = part.findObject('SHAPE') as go.Shape;
          const obj = part.data.geo.copy();
          const pos = new go.Point(obj.startX - shape.strokeWidth / 2, obj.startY - shape.strokeWidth / 2);
          part.position = pos;

          return part;
        }
      }));
  }

  makeGeo(diag) {
    const data = new go.Geometry(go.Geometry.Line);

    data.startX = diag.firstInput.documentPoint.x;
    data.startY = diag.firstInput.documentPoint.y;
    data.endX = diag.lastInput.documentPoint.x;
    data.endY = diag.lastInput.documentPoint.y;
    data.normalize();
    return data;
  }

I don’t know what all of your requirements are, but here’s my attempt at implementing what I think you are asking for:

<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<script src="../extensions/DragCreatingTool.js"></script>
<script id="code">
  // Customize the DragCreatingTool extension to always draw a simple line.
  function DragCreatingLineTool() {
    DragCreatingTool.call(this);

    this.delay = 0;  // always canStart(), so PanningTool never gets the chance to run
    this.box =
      go.GraphObject.make(go.Part,
        { layerName: "Tool" },
        go.GraphObject.make(go.Shape,
          { name: "SHAPE", fill: null, stroke: "cyan", strokeWidth: 2 })
      );

    this.archetypeNodeData = { category: "Line" };

    // reuse two simple Line Geometrys
    var slash = new go.Geometry(go.Geometry.Line);
    slash.startX = 1;
    slash.startY = 0;
    slash.endX = 0;
    slash.endY = 1;
    DragCreatingLineTool.SlashGeometry = slash;

    var backslash = new go.Geometry(go.Geometry.Line);
    backslash.startX = 0;
    backslash.startY = 0;
    backslash.endX = 1;
    backslash.endY = 1;
    DragCreatingLineTool.BackslashGeometry = backslash;
  }
  go.Diagram.inherit(DragCreatingLineTool, DragCreatingTool);

  DragCreatingLineTool.prototype.insertPart = function(bounds) {
    var arch = this.archetypeNodeData;
    if (arch === null) return null;
    // decide whether to use Slash or Backslash
    arch.slash = (this.diagram.lastInput.documentPoint.x < this.diagram.firstInput.documentPoint.x);
    return DragCreatingTool.prototype.insertPart.call(this, bounds);
  }


  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            "resizingTool.minSize": new go.Size(0, 0),  // allow horizontal or vertical lines
            "undoManager.isEnabled": true,
            "ModelChanged": function(e) {     // just for demonstration purposes,
              if (e.isTransactionFinished) {  // show the model data in the page's TextArea
                document.getElementById("mySavedModel").textContent = e.model.toJson();
              }
            }
          });

    // install the custom DragCreatingTool
    myDiagram.toolManager.mouseMoveTools.insertAt(2, new DragCreatingLineTool());

    // The regular node and link templates don't really matter for this demo

    myDiagram.nodeTemplateMap.add("Line",
      $(go.Node,
        { resizable: true, resizeObjectName: "SHAPE" },
        new go.Binding("position", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Shape,
          {
            name: "SHAPE",
            isGeometryPositioned: true,
            desiredSize: new go.Size(100, 100),
            geometry: DragCreatingLineTool.BackslashGeometry
          },
          new go.Binding("geometry", "slash", function(slash) {
            return slash ? DragCreatingLineTool.SlashGeometry : DragCreatingLineTool.BackslashGeometry;
          }),
          new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
          new go.Binding("stroke", "color"),
          new go.Binding("strokeWidth", "thickness"))
      ));

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", color: "lightblue" },
      { key: 2, text: "Beta", color: "orange" },
      { key: 3, category: "Line", color: "green", thickness: 2 },
      { key: 3, category: "Line", color: "blue", thickness: 4, slash: true }
    ],
    [
      { from: 1, to: 2 }
    ]);
  }
</script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</body>
</html>

Hi @walter, apologies for not having to be able to explain my requirement to you clear enough.

Here is what I am looking for -
line_draw

I want to be able to draw a simple straight line exactly like this on my layout while dragging, I don’t need the measurement it shows though.

This GIF is an example from the wallbuildingtool.ts in Floor Planner .
Although it is an overkill for my requirement to be able to reuse it and it is a gojs Group, A simple gojs Node would suffice in my case, if it is at all possible.

  // Customize the DragCreatingTool extension to always draw a simple line.
  function DragCreatingLineTool() {
    DragCreatingTool.call(this);

    // reuse two simple Line Geometrys
    var slash = new go.Geometry(go.Geometry.Line);
    slash.startX = 1;
    slash.startY = 0;
    slash.endX = 0;
    slash.endY = 1;
    DragCreatingLineTool.SlashGeometry = slash;

    var backslash = new go.Geometry(go.Geometry.Line);
    backslash.startX = 0;
    backslash.startY = 0;
    backslash.endX = 1;
    backslash.endY = 1;
    DragCreatingLineTool.BackslashGeometry = backslash;

    this.delay = 0;  // always canStart(), so PanningTool never gets the chance to run
    this.box =
      go.GraphObject.make(go.Part,
        { layerName: "Tool" },
        go.GraphObject.make(go.Shape,
          {
            name: "SHAPE",
            geometry: DragCreatingLineTool.BackslashGeometry,
            fill: null,
            stroke: "magenta",
            strokeWidth: 2
          })
      );

    this.archetypeNodeData = { category: "Line" };
  }
  go.Diagram.inherit(DragCreatingLineTool, DragCreatingTool);

  DragCreatingLineTool.prototype.isSlash = function() {
    var s = this.diagram.firstInput.documentPoint;
    var e = this.diagram.lastInput.documentPoint;
    return (e.x < s.x && e.y > s.y) || (e.x > s.x && e.y < s.y);
  }

  DragCreatingLineTool.prototype.doMouseMove = function() {
    this.box.elt(0).geometry = this.isSlash() ? DragCreatingLineTool.SlashGeometry : DragCreatingLineTool.BackslashGeometry;
    DragCreatingTool.prototype.doMouseMove.call(this);
  }

  DragCreatingLineTool.prototype.insertPart = function(bounds) {
    var arch = this.archetypeNodeData;
    if (arch === null) return null;
    // decide whether to use Slash or Backslash
    arch.slash = this.isSlash();
    return DragCreatingTool.prototype.insertPart.call(this, bounds);
  }

Thanks, it works.

I have two more questions, how do we make the line selection adornment to be shape of line itself, rather than a rectangle.
And, how do I calculate the actual length of the line drawn ? I have node.actualBounds.width and node.actualBounds.height , but what if the line is not straight ?

https://gojs.net/latest/intro/selection.html

Sorry, but getting the length of a path is not in the Geometry API.

Can calculating the hypotenuse of the rectangle be a potential solution to this ?

If you only care about a Geometry of type Line, yes.

In this case yes, I do only care about it.
Very well then. Thanks.