Stop timer Component with C#

Hello,

I’ve created a component, where input is a line an boolean. I would like to move a point along this line, therefore a I’ve divided a line into 10 segments. From the one of the segments I’ve defined a vector, so the point has the distance and direction to move.

To move point in grasshopper I am using timer (also trigger) Component. How can I stop this timer/trigger component, if the point reaches the end of the line. Or at least, will change the direction and make the point to go back to the start of the line.

Here is the C# code of this component:

public class Motion : GH_Component
{

    public Motion()
      : base("MyComponent1", "Nickname",
          "Description",
          "Category", "Motion")
    {
    }

    protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
        pManager.AddCurveParameter("Curve", "C", "Offset curve for motion", GH_ParamAccess.item);
        pManager.AddBooleanParameter("Reset", "Reset", "Reset", GH_ParamAccess.item);

    }

    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        pManager.AddPointParameter("Particle", "Particle", "Particle", GH_ParamAccess.item);
        pManager.AddPointParameter("Start", "Start", "Start", GH_ParamAccess.item);
        pManager.AddPointParameter("End", "End", "End", GH_ParamAccess.item);
        pManager.AddVectorParameter("Vector", "Vector", "Vector", GH_ParamAccess.item);
        pManager.AddPointParameter("Division points", "Division poins", "Division poins", GH_ParamAccess.item);
    }

    Point3d currentPosition;
    protected override void SolveInstance(IGH_DataAccess DA)
    {
        Curve road = new LineCurve();
        DA.GetData(0, ref road);

        bool iReset = true;
        DA.GetData(1, ref iReset);

        double road_length = road.GetLength();
        double seg_length = road_length / 10.0;
        Point3d[] points;
        road.DivideByLength(seg_length, true, out points);

        List<Point3d> pointsList = points.ToList();

        Vector3d iVelocity = new Vector3d(points[1].X - road.PointAtStart.X, points[1].Y - road.PointAtStart.Y, 0);

        if (iReset)
        {
            currentPosition = new Point3d(road.PointAtStart.X, road.PointAtStart.Y, 0.0);
            return;
        }
        
            currentPosition += iVelocity;


        DA.SetData(0, currentPosition);
        DA.SetData(1, road.PointAtStart);
        DA.SetData(2, road.PointAtEnd);
        DA.SetData(3, iVelocity);
        DA.SetDataList(4, pointsList);

    }

}

Here is a screenshot, where you can see, that the point is out of the line (for now):

Thank you in advance!


Snipaste_2022-04-17_18-25-59
I think you need some global variables to record something.
The prototype is really easy so I skipped the comments, I think you can understand the code in no time.

In this code the number run from 0 to 10 and then from 10 to 0 repeatly.

2 Likes


trigger.gh (11.5 KB)

This is what you need to output all your 5 required data.
I don’t think it is a very good idea to put all these geometry calculations into one component, which will be triggered many many times later.
A better way should be controlling the “loop/stop at the end/go back at the end” kind of thing in a separated module, and in this case, all geometry calculation such as curve division should be only done once.

By the way, if you like it to stop instead of turn around when reaching the end.
It would be really tricky to really “stop the trigger” because the trigger is another component.
It can be done, but I do not recommend it.
A much simpler way is to just implement something like below in your code:
if n<max then do the thing, else do nothing.

1 Like

Hello @11165, Thank you!
An here how I’ve adjusted it:

protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddCurveParameter(“Curve”, “C”, “Offset curve for motion”, GH_ParamAccess.item);
pManager.AddBooleanParameter(“Reset”, “Reset”, “Reset”, GH_ParamAccess.item);

    }

    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        pManager.AddPointParameter("Particle", "Particle", "Particle", GH_ParamAccess.item);
    }        
 
    bool direction;
    int n;

protected override void SolveInstance(IGH_DataAccess DA)
{
Curve road = new LineCurve();
DA.GetData(0, ref road);

        bool iReset = true;
        DA.GetData(1, ref iReset);

        double road_length = road.GetLength();
        double seg_length = road_length / 10.0;
        Point3d[] points;
        road.DivideByLength(seg_length, true, out points);

        if (iReset)
        {
            n = 0;
            direction = true;
        }

        if (direction) n++;
        else n--;

        if ((n == 0) || (n == 10)) direction = !direction;

        DA.SetData(0, points[n]);

    }

I am just wondering:
Why, if I try to apply this logic on position of the point (not on its index, like in the code above), isn’t the code working correctly?

Here the code, where I am using position of the point, not the index:

protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
        pManager.AddCurveParameter("Curve", "C", "Offset curve for motion", GH_ParamAccess.item);
        pManager.AddBooleanParameter("Reset", "Reset", "Reset", GH_ParamAccess.item);

    }

    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        pManager.AddPointParameter("Particle", "Particle", "Particle", GH_ParamAccess.item);
    }
    
    
    Point3d currentPosition;
    bool direction;

    protected override void SolveInstance(IGH_DataAccess DA)
    {
        Curve road = new LineCurve();
        DA.GetData(0, ref road);

        bool iReset = true;
        DA.GetData(1, ref iReset);

        double road_length = road.GetLength();
        double seg_length = road_length / 10.0;
        Point3d[] points;
        road.DivideByLength(seg_length, true, out points);
        Point3d startPoint = new Point3d(road.PointAtStart.X, road.PointAtStart.Y, 0.0);
        Point3d endPoint = new Point3d(road.PointAtEnd.X, road.PointAtEnd.Y, 0.0);

        List<Point3d> pointsList = points.ToList();

        Vector3d iVelocity = new Vector3d(road.PointAtStart.X - points[1].X, road.PointAtStart.Y - points[1].Y, 0);

        if (iReset)
        {
            currentPosition = startPoint;
            direction = true;
        }

        if(direction)currentPosition += iVelocity;
        else currentPosition -= iVelocity;

        if(currentPosition == startPoint || currentPosition == endPoint)
            direction = !direction;


        DA.SetData(0, current position);

    }

I usually try to avoid dealing with float numbers.
If I had to, I will use tolerance.
In your case, there is little chance that “currentPosition == startPoint”
A more common way is something like “Abs(currentPosition - startPoint) < 0.001”, while 0.001 is tolerance according to your actual demand.

I think you can spend some time learning basic concepts of how computer deal with float numbers since your work require a huge amount of programming time.

https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/overview/reals.html

1 Like

Since you are dealing with point3d variables instead of float/int numbers.
The equality “=” can work, but “<” and “>” no longer work.
For “=” as I mentioned before, there is very little chance that the equation works.
Only when abs(x1-x2)<tolerance and abs(y1-y2)<tolerance can this point=point equation work.

I suggest using something like:

param = road.ClosestPoint(currentPosition);
CPoint = road.PointAt(param);
Distance = currentPosition.DistanceTo(CPoint);
If(Distance > 0.001) //or 0.001 can be other values/variables.
direction = !direction;

(these code are not tested in GH, I typed here directly, so there might be mistakes, but you can get the idea :grin:)

1 Like

Hi there, I am a noob in C# programming. If I only need the code to run from 0 to 10 and stop and 10. How should I do it?

Thanks in advance!

Chua

you are replying to a post that is whole 2 years ago
this is not the way a forum works.

for your question. you will have to create a new post
for 2 reasons:

1: do not dig old post
2: do not ask questions that is not related to original content

I can not help you because it’s been 2 years and I no longer use C# and I don’t have rhino and grasshopper on my pc any more.

paste my previous code to chatgpt and tell it your new demand. let it help you.
or write a new post, and wait for a reply.

here it is


but I can not test for you