Giter VIP home page Giter VIP logo

Comments (28)

skeate avatar skeate commented on May 19, 2024

To see if I understand this correctly: add multiple Leaflet.timeline layers, and all of those get handled by one timeline control, which shows all events from all timeline layers?

Sounds very reasonable, and would probably help clean up the code in reworking it. Right now there's a lot of interdependency between the control and the layer; implementing this would sort of force a separation.

Could get hairy on edge cases, e.g. the timeline is currently playing and then the user toggles a layer.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

You have it exactly. The cleanest from the user API viewpoint. Would be if be to have the first L.Timeline work as normal, and if you chose to add a second, it would only add the GeoJSON layer, and would "connect" to the original Timeline control. If you are refactoring, then I would make each layer subscribe to the Timeline control, and seperate the code modularly. But an alternative is to make the TimeLineControl (TLC) the master and have the layers register with it, and it loops through the layers to "animate" them.

There probably are other ways to tackle this also.

Our use case is a small area of land where we have lots of sensors (internet of things) and we are trying to compare what features they pick up and which they don't and what footprints they have and which they do not. We want to see all the A/B choices.

My worry right now is about the Date() resolution. Sensor data is coming in at 100Hz in some cases and so I need the start and stop to be about 10ms apart on the timeline.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

RE: edge conditions

If the master is the layer (it does the animating) and just subscribes to time events, you can handle the layer invisible issue cleanly. You could also have the TLC as master and simply update the GeoJSON layer if it was invisible. I would leave the tick marks as they were even if a layer was turned off, it seems too much work to keep separate bags for each set of tic marks.

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

Regarding your last point, I think that shouldn't matter. The timeline automatically adjusts to the endpoints of the data given to it, and calculates a step amount based on that. I don't remember anything forcing the step to be an integer.

It does raise a point about the multiple-layers thing. I guess there could be two modes for merging, offset and absolute. Basically if you have one layer which is 10ms of data at noon on day 1, then another layer which is 10ms of data at noon on day 2, then the timeline will show two blips one day apart for absolute mode, or one 10ms span from 0 to 10ms in offset mode

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Well, most use cases I can think of where you have 2+ layers is where the data actually overlaps in time. Not blips widely scattered. You want to do A & B comparison of data at the same time. If data is for a few seconds each day (with lots of data at each time). Then it is going to be really hard to get the duration and steps with the right granularity. You would have to go to a different time model, where gaps are fine and the timeline moves by time-varying intervals based on data presence.

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

Offset mode would basically make the layers behave as if the first start time for each was the same for all.

So...

Times of dataset 1:   0   5  10  15
Times of dataset 2: 100 106 112 113

Absolute:

1    1    1    1       2     2     22
|----+----+----+ . . . +----+----+----|
0    5   10   15      100  105  110  115

Offset:

1
2         12        1   2 2   1
|---------+---------+---------+
0         5        10        15

(note: would've been better to show dataset 1 and 2 as starting at non-zero times to show that offset would always start at 0 regardless of the datasets.. but I already typed this up as it is 😓)

Because the timeline just jumps by a certain step each frame, if the data you have is in tiny clusters relative to the overall time span, the animation would show it all happening in one frame. (Though using the next/previous would still work, because those just find the next point in the data, they don't move stepwise)

The same thing could be achieved by just preprocessing the data to align them all to the same start point, but this way might be easier for some people.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I would not be fond of the offset mode. I do not want the analysis framework shifting the times of my data to indicate overlap when they really are separate.

Of course, I might be looking at this all through my "soda straw" :-(

But what I have is a lot of sensors (LIDAR, Stereo Vision, Doppler Radar, etc) all reporting of features. What I want to do is FUSION of the sensors. Each sample is time-stamped with an absolute GPS clock value. This is key for the FUSION, since I need to know what sensors see simultaneously. I don't want an shift of timeline. I want to see in Leaflet the raw overlay and figure out what I need for Fusion algorithms.

Also I really like what you did with intervalFromFeature, function, since I don't get the data stream tagged with start/stop. Instead I get a time stamp for each sample. Knowing the sample rate (4Hz, 50 Hz, 1000Hz) I can then use the intervalFromFeature to compute start/stop.

Yes, there might be need to overlap separate runs, but I have pretty good tools for bulk processing the JSON if I want to (SAFE FME). So if I want to align separate runs on separate days I just have to add an offset to the intervalFromFeature function. That strikes me as the best way to get offsets.

BTW, I assume you know about the trade-offs of continuous time vs. discrete time:

https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time
http://math.stackexchange.com/questions/348560/continuous-time-versus-discrete-time-stochastic-models

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

The offset vs absolute mode would be a toggleable option, defaulting to absolute. Kind of in keeping with the "minimal external processing needed" course this has been taking (e.g. with the intervalFromFeature function that vencax wrote).

Also, while I don't think it's quite possible right now, the amount of work to shift it away from Date-based values on the slider is fairly negligible. It would still be the default, since this is Leaflet.timeline, but you could at least switch that functionality out for any kind of scale you want -- unitless floating points, temperatures, populations...

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Now that is a fascinating generalization, and I applaud it.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Perhaps this should be a different issue, but I noticed that the "change" event does not return much useful info. While you are refactoring could you have it return the current time on the timeline, and the list of GeoJSON features that are active?

Why do I ask?

I have a GeoJSON file that has point features for the location of a automobile and its heading. I am using a RotableMarker (https://github.com/bbecquet/Leaflet.RotatedMarker) that shows that marker. I just allow the GeoJSON layer to default for pointToLayer, it would have a blue marker. I want it to set the makers as invisible on load, and then to render it manual on each timeline change event (translate and rotate).

I think you could stick the active features for the timeline into a jagged array, with a bin for each bucket in the duration/step. Then put the active features for that bucket of time in the list. It should be easy to return that pointer with the event object.

What do you think?

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

You can (I believe) already access the time with L.Timeline#time, and the currently displayed layers with L.Timeline#displayedLayers, e.g.:

var layer = L.timeline(...);
layer.on('change', function() {
  var currentTime = layer.time;
  var currentLayers = layer.displayedLayers;
});

It's easy enough to throw that into the change event data (and I will), but if you want to use it now you should be able to.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I was hoping for convenience values attached to the event, because what I need is less the actual time, but more the features that are active at CurrentTime. But both would be good:

e.time = Timeline.Date
e.features  = [ {featureA, featureB, ...]; // across all GeoJson Timeline objects controlled by the timeline.

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

Right, that's what's in displayedLayers (though not across all layers since multiple layers on one control isn't a thing yet).

Could perhaps better be called displayedFeatures

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Neat. Tried it and it works great. BTW, if you want another demo of what you can do with your timeline, I have a simple one that could be in the examples for doing cloud and pollution spills. It is about 10 seconds of animation.

croppercapture 1

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

I was actually planning on adding something in the readme asking for anyone who uses it to let me know what sorts of things they're doing with it, and maybe including links to examples "in the wild" (with permission of course). I've only seen a few, but they've all been really neat.

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

I've published a beta of 1.0.0, which (among other things) allows multiple L.Timeline layers to be controlled by one L.TimelineSliderControl.

Please try it out, and let me know if anything's awry, either with the code or the docs. Thanks!

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I will, but one quick question, that is not covered in the documentation. What we call a klutz question: If you want multiple GeoJSON layers controlled by a single Timeline, what do you do? Do I guess right that you just keep adding Leaflet.Timelines()? What if they have different time ranges, durations, steps, time, formoutOutput, enablePlayback? And if not, then how does one add a second GeoJSON layer to the existing timeline?

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

Yeah, each GeoJSON layer would be a separate L.Timeline. I need to add something to add more features to an existing layer, but for now if you want multiple separate features in one layer you could wrap them up in a GeoJSON featureCollection.

The layers themselves no longer have a concept of duration, steps, etc. All of that is managed by the control. The only options for the layers is getInterval (previously intervalFromFeature) and drawOnSetTime.

The layers expose the start (x) and end (y) of their datasets and the control figures out the range it should have based on all of the layers it manages (min of xs, max of ys). You could also specify a start and end in the control's options, and then the playback range is always between those values, no matter what data exists on the layers.

The steps and duration aren't really meant to have anything to do with the data. They're a means of mucking with the playback speed. Individual points are accessible if necessary by dragging the slider and/or using the next/prev buttons

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Ok, I got it sorry for being dense. I am working on other parts of the problem this morning, and the brains cells for javascript are being used for UDP, Python, WebSockets, and a DotNet C# gateway that is translating from binary UDP sockets to GeoJSON for this layer. I want to get this tested this afternoon.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

In addition to Polyline and Polygon layers, I have GeoJSON layer that has point data (the location of a car). It seemed to me a waste to instantiate over 5,000 marker objects for a GeoJSON timeline for that layer. So what I tried to do is set a GeoJSON.filter function that checks to see if the GeoJSON has GPS property, and not "show" that GeoJSON layer.

         this.show = function (feature, layer) {
             var type = feature.properties.type;
             switch (type) {
                 case "Oxford.GPS":
                     return false;
                 default:
                     return true;
             }
         }

Then I catch the change event and get the list of objects, (and i was going to the properties to update a single marker (which is actually has a rotate with it)

Now, it is true that I get the change event for each object on the timeline (including these point objects) But the list of changed objects is 0, when I filter. But it is fine if I don't.

         this.newTime = function (e) {
             var currentTime = timeLayer.time;
             var currentLayers = timeLayer.displayedLayers;
             console.log("Timeline Change: " + JSON.stringify(e.type));
             $.each(currentLayers, function (index, layer) {
                 var bag = layer.geoJSON.properties;
                 var type = bag.type;
                 var loc = layer.geoJSON.geometry.coordinates;
                 switch (type) {
                     case "Oxford.GPS":
                         Overlays.doGPS(loc, bag);
                         break;
                     default:
                         console.log("overlays.newTime: unknown GeoJSON type: " + type);
                 }
             });
         }

        this.doGPS = function (loc, props) {
             CarState.lat = loc[1];
             CarState.lon = loc[0];
             CarState.alt = loc[2];
             CarState.heading = props.heading;
             CarState.time = props.start;
             CarState.valid = props.valid;
             switch (props.correction) {
                 case 0:
                     CarState.correction = "None";
                     break;
                 case 1:
                     CarState.correction = "WAAS";
                     break;
                 case 2:
                     CarState.correction = "Differential";
                     break;
                 case 3:
                     CarState.correction = "RTK";
                     break;
                 case 4:
                     CarState.correction = "Other";
                     break;
             }
             Mapper.update();
         }

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

If you're filtering out features of type "Oxford.GPS", they never get added to the L.Timeline layer, and thus are never in displayedLayers.

But I think if I switch getDisplayed() back to the way it used to work, then it would return all the features at the current time, even if not actually displayed on the map. (though, a new name would be in order for that)

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

Right, I suspected that. But the odd thing was the change events were happing based on where the "invisible" items were. So they seemed to be added to the GeoJSON layer. So I was hoping it would be possible to get even the filtered ones back with the getDisplayed() without too much hassle.

getAllCurrent() ? (better than getDisplayedAndNotDisplayed() )

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I know I am going to have to learn coffeeScript so I can help you directly (and figure out how to get gitHub source control to work with our firewall, I can do local git repositories, and our local server, but I.T. is nasty here, and we have real problems with going through the firewall. So I hope you don't mind and I will post the issues I have below.

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

FWIW it's no longer written in Coffeescript; it's ES2015 (aka ES6) now. Still transpiled, but it's Javascript -- just from the future.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024
  1. I was finding that the POINT features, which default to a marker icon, were disappearing at random points in the timeline. It was driving me crazy. The lat/long was fine. What I nailed it down was the that Leaflet sets z-index based on latitude. So for stretches the car icon would disappear. What I think is the source is that they L.Timeline is adding all the markers to the marker pane, and that is creating 5K z-ordered values. And leaflet and for a lot of markers the Z-index is negative. so it goes below the tile layer.

This could be all fixed for me if I could specify the GeoJSON filter: function, and stilll gett the getDisplayed() function to return all of them. Right now I have a kludge to sett zIndexOffset for the car icon marker to 10,000. So that it stays on top of all the junk in the marker pane. I don't know if this is going to be an issue with the PolyLine and Polygon GeoJSON paths.

  1. For my application, I first create the L.TimeLineControl() and then the user chooses to add the L.Timelines by choosing log files (in GeoJSON Timeline Format) and this created new L.Timelines and adds them to the overlay control, This is NOT working.

Multiple issues;
a. start/stop is not known when the initial timellineControl is created.
b. I hacked this to have some reasonable values, but the subsequent load of the Timeline does not work at all. Here is what I used:
start: "2015-11-19T15:51:56.2660000Z",
end: "2015-11-19T15:52:57.3530000Z",
c. Bug: the formatOutput( date) function is getting a string value not a DateTime. so date.toISOString() does not work. After the initial string value of "2015-11-19T15:51:56.2660000Z",, it is feeding it a numeric value of 2015, or 44, or other values. clearly not a unix time.

  1. What are you going to do if a person uses the LayerControl to turn on/off a layer
  2. Why is the change event associated with a layer, seems more logical with the TimelineSlider, especailly since the getDisplayed is for the slider, not with the layer. Or swap both to the laery.

Minor documentation issues:

  1. Show how to created multiple TimeLines for one Slider (and add/remove Timelines) while leaving the Slider up.
  2. updateDisplayedLayers() reffered to but not described (very minor, I won't use this)
  3. since formatOutput is only for dates, why not call it formatDate, and document that this is for showing the date on the TilelineSlider control.
  4. Clarify that steps and duration is only used for the PLAY function of the TimelineSlider, but that clicking on locations does not use this.
  5. waitToIUpdateMap is really confusing. it seems that true means the same as drawOnSetTime since you say that if it is true, only the date is set, not the map. If formating the date is a problem, then you could call it manualDateUpdate, and manualMapUpdate, and have both false as defaults.

I probably need functions for setStart() and setEnd() since different logs will have different time ranges.

BTW, I did something slightly illegal, and extended the GeoJSON spec, At the end of each GeoJSON file I load I put a bunch of metadata, which is ignored in all the programs I have tried.

....

{"type":"Point","coordinates":[-83.697503617676588,42.302661024805644,278.33480834960938]},"type":"Feature"},

{"properties":{"heading":275.377625,"correction":3,"valid":true,"type":"Oxford.GPS","start":"2015-11-19T15:52:57.3530000Z","end":"2015-11-19T15:52:57.3630000Z"},
"geometry":{"type":"Point","coordinates":[-83.697504531266375,42.302661093646158,278.33636474609375]},"type":"Feature"}
   ],
  "version": "1.0",
  "samples": 6152,
  "start": "2015-11-19T15:51:56.2660000Z",
  "end": "2015-11-19T15:52:57.3530000Z",
  "duration": 61087.00,
  "description": "demo"
}

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I found this undocumented method in your source: addTimelines() and did the call, but it did not update the TimelineSlider. Hey, thanks for switching to ES6!

from leaflet.timeline.

skeate avatar skeate commented on May 19, 2024

since formatOutput is only for dates, why not call it formatDate, and document that this is for showing the date on the TilelineSlider control.

The name was actually changed specifically because it doesn't refer only to dates anymore. The default behavior does treat everything like a date, but it's all overridable.

from leaflet.timeline.

DrYSG avatar DrYSG commented on May 19, 2024

I think I got you. You are saying that begin/end pairs in the GeoJSON as well as the axis of the "timeline" can be any continuous monotonically increasing value. E.G. instead of time, one could have luminence, chrominance, or pressure,

Any comment on my other findings? Would some of the "geoJSOn files that I am using help". I want to help contribute to this.

from leaflet.timeline.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.