Standalone Tool C# WPF create 3D lines in Speckle and view it on Website

Hi,

I’m a newbie. I’m developing new standalone tool to build model 3D (Steel Bridge). Could I use Visual Studio (C# WPF) to create 3D lines in speckle and view 3D model on website? Could you give me simple example to do that. Just create 3d line and send to speckle, and see it on website?

Thanks!

One example send room boundaries from revit :
you can learn more document at : Introduction | Speckle Docs

using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Windows;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Objects;
using Objects.Geometry;
using Objects.Primitive;
using Objects.Structural.Analysis;
using Speckle.Core.Api;
using Speckle.Core.Credentials;
using Speckle.Core.Kits;
using Speckle.Core.Models;
using Speckle.Core.Transports;
using Speckle.Newtonsoft.Json;
using Curve = Autodesk.Revit.DB.Curve;
using Line = Objects.Geometry.Line;
using MessageBox = System.Windows.MessageBox;
using Point = Objects.Geometry.Point;

namespace ExyteRevit.Plugins.DataExtraction.Command;

[Transaction(TransactionMode.Manual)]
public class RoomExtractionSpeckle : IExternalCommand
{
    private const double TOLERANCE = 0.0164042; // 5mm in ft
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        return Task.Run(async () => await ExecuteAsync(commandData)).Result;
    }
    
    private Task<Result> ExecuteAsync(ExternalCommandData commandData)
    {
        MessageBox.Show("Extract Speckle Data");
        UIApplication uiapp = commandData.Application;
        Document doc = uiapp.ActiveUIDocument.Document;
        // define the base object
        var commitObject = new Base();
        List<RoomData> Rooms = new List<RoomData>();
        // Get all room in revit 
        FilteredElementCollector collector = new FilteredElementCollector(doc);
        IList<Element> elements = collector.OfClass(typeof(SpatialElement)).ToElements();
        Autodesk.Revit.DB.SpatialElementBoundaryOptions ops = new SpatialElementBoundaryOptions();
        SpatialElementBoundaryLocation boundloc = Autodesk.Revit.DB.AreaVolumeSettings.GetAreaVolumeSettings(doc)
            .GetSpatialElementBoundaryLocation(SpatialElementType.Room);
        ops.SpatialElementBoundaryLocation = boundloc;
        // get all properties of object
        foreach (Element element in elements)
        {
            var data = new object();
            ParameterSet parameters = element.Parameters;
            foreach (object parameter in parameters)
            {
                data = SnoopProperties(parameter);
            }
            Room? room = element as Room;
            var boundarySegments = room.GetBoundarySegments(ops);
            List<Line> lines = new List<Line>();
            foreach (IList<BoundarySegment> boundarySegment in boundarySegments)
            {
                foreach (BoundarySegment segment in boundarySegment)
                {
                    try
                    {
                        Autodesk.Revit.DB.Line line = segment.GetCurve() as Autodesk.Revit.DB.Line;
                        Line lineToSpeckle = LineToSpeckle(line);
                        lines.Add(lineToSpeckle);
                    }
                    catch (Exception )
                    {
                       // do nothing
                    }
                }
            }
            RoomData roomData = new RoomData()
            {
                Parameters = data,
                Name = element.Name,
                ElementId = element.Id.IntegerValue,
                Lines = lines,
            };
            Rooms.Add(roomData);
        }
        commitObject["Rooms"] = Rooms;
        commitObject.totalChildrenCount = Rooms.Count;
        Account defaultAccount = AccountManager.GetDefaultAccount();
        string streamId = "9f233a81e7";
        string branchName = "main";
        ServerTransportV2 serverTransportV2 = new ServerTransport(defaultAccount, streamId);
        string id = Operations.Send(commitObject, new List<ITransport>() {serverTransportV2}).Result;
        var client = new Client(defaultAccount);
        var branch = client.BranchGet(streamId, branchName).Result;
        // random 1 to 100
        string resultCommit = client.CommitCreate(
            new CommitCreateInput
            {
                streamId = streamId,
                branchName = branch.name,
                objectId = id,
                message = "Revit Element Room",
                totalChildrenCount = Rooms.Count,
            }).Result;
        return Task.FromResult(Result.Succeeded);
    }
    
    public Line LineToSpeckle(Autodesk.Revit.DB.Line line, string units = null)
    {
        var u = units ?? "mm";
        var l = new Line { units = u };
        l.start = PointToSpeckle(line.GetEndPoint(0));
        l.end = PointToSpeckle(line.GetEndPoint(1));
        l.domain = new Interval(line.GetEndParameter(0), line.GetEndParameter(1));

        l.length = line.Length;
        return l;
    }
  
    Point PointToSpeckle(Autodesk.Revit.DB.XYZ point)
    {
        return new Point(point.X, point.Y, point.Z, "mm", "revit");
    }
  
}

public class RoomData : Base
{
    public List<Objects.Geometry.Line> Lines { get; set; }
    public string Name { get; set; }
    public int ElementId { get; set; }
    public object Parameters { get; set; }
}

4 Likes

Hey @kt.developer.2022 ,

Here’s a very simple C# sample console app that does just that: GitHub - teocomi/speckle-lines-sample: quick sample on using speckle's api to create some lines

Any questions just ask!

3 Likes

Thanks very much. That’s exactly what I want!

Hi Teocomi,

Based on your sample, I try to send 2 lines with my account and stream. But It doesn’t work. Could you help me?

The my code is shown as below:

using Speckle.Core.Credentials;
using Speckle.Core.Transports;
using Speckle.Core.Api;
using Speckle.Core.Models;
using Speckle.Core.Transports;
var line1 = new Objects.Geometry.Line(new Objects.Geometry.Point(0, 0, 0), new Objects.Geometry.Point(100, -200, 50));
var line2 = new Objects.Geometry.Line(new Objects.Geometry.Point(0, 0, 0), new Objects.Geometry.Point(500, 100, 600));

var commitData = new Base();

commitData["data"] = new List<Base> { line1, line2 };

var account = new Account();
account.token = "REMOVED-FOR-SECURITY";
account.serverInfo = new ServerInfo
{
    url = "https://speckle.xyz/"
};

var stream = "https://speckle.xyz/streams/1927593f17";

var streamId = "1927593f17";
var branchName = "main";
var client = new Client(account);
var transport = new ServerTransport(account, streamId);

var objectId = await Operations.Send(
                              commitData,
                              new List<ITransport> { transport },
                              disposeTransports: true);

var commitId = await client.CommitCreate(
          new CommitCreateInput
          {
              streamId = streamId,
              branchName = branchName,
              objectId = objectId,
              message = "Hello"
          });
        

System.Diagnostics.Process.Start(
    String.Format(@"https://speckle.xyz/streams/1927593f17/commits/{commitId}") );

Could you describe “it doesn’t work”?

Doesn’t send?
Doesn’t add lines?
Doesn’t authenticate?

I’ll look at what you have there in the meantime.

1 Like

Hi Jonathon,

I use visual studio, after I run this code and check in the stream on speckle website. No data sent to stream.

It working in my side :

// See https://aka.ms/new-console-template for more information
using Speckle.Core.Credentials;
using Speckle.Core.Transports;
using Speckle.Core.Api;
using Speckle.Core.Models;
Console.WriteLine("Hello, Speckle!");


var line1 = new Objects.Geometry.Line(new Objects.Geometry.Point(0, 0, 0), new Objects.Geometry.Point(100, -200, 50));
var line2 = new Objects.Geometry.Line(new Objects.Geometry.Point(0, 0, 0), new Objects.Geometry.Point(500, 100, 600));

var commitData = new Base();

commitData["data"] = new List<Base> { line1, line2 };

var account = new Account();
account.token = "your token";
account.serverInfo = new ServerInfo
{
    url = "https://speckle.xyz/"
};
var streamId = "4afea2f6c6";
var branchName = "main";
var client = new Client(account);
var transport = new ServerTransport(account, streamId);

var objectId = await Operations.Send(
    commitData,
    new List<ITransport> { transport },
    disposeTransports: true);

var commitId = await client.CommitCreate(
    new CommitCreateInput
    {
        streamId = streamId,
        branchName = branchName,
        objectId = objectId,
        message = "Hello"
    });
Console.WriteLine($"https://speckle.xyz/streams/{streamId}");
1 Like

Thanks. But from my side, I used the same your code exception some changes about token and streamId, I got the error as below:

Could you help me?

This is my visual studio project I use to test.
Test.rar (2.1 MB)

You can try with SDK source from here :

1 Like

Random thought but… can you double check your token has the correct scopes to read/write streams? It should have streams:read if you want to access stream data, and stream:write if you want to be able to make commits.

If you don’t, then you can create a new token and add those in the scopes dropdown.

1 Like