OpenLayers fitting before add features - javascript

Problem: Open layers is fitting to map and only after is adding features (visually), how can i avoid this?
im doing this
step 1 - creating the features
var feature = new ol.Feature({...});
step 2 - adding them to source
source.addFeature(feature);
step 3 - and fitting like this
view.fit(source.getExtent(), { duration: 1000 });
but visually is showed step 3 -> step 1 -> step 2
i want to do step 1 -> step 2 -> step 3 (by code order)

You can try and fit the view on addfeature
source.on('addfeature', function() {
view.fit(source.getExtent());
});

The best way to achieve this is to create the layer without a source, and set the source of the layer after view.fit:
const layer = new ol.layer.Vector();
const source = new ol.source.Vector();
source.addFeature(feature);
view.fit(source.getExtent());
layer.setSource(source);

Related

Vue Draggable - How to only replace item chosen to prevent shifting all other items on grid?

Here's an example to test:
https://codesandbox.io/s/j4vn761455?file=/src/App.vue:112-116
Step 1: Drag 4 to 5. As you see, 4 and 5 switch places
Step 2: Drag 1 to 6, as you see, 1 goes where 6 was, 6 gets pushed to the side, and 2, 3, 4, and 5 all shift over.
I would like though is to keep existing items untouched, moving 1 and 6 should move 1 to 6 and 6 to 1 space on the grid. All other items should remain in their spaces.
I have tried using sort=false this had no effect, and without a group=, it disables all dragging.
Is this possible?
I'd like the items in the grid to be stationary and only moved based on desired selection. If I'm not using the right tool, is there something else that could accomplish this? Think about if the grid was icons, it does make a good UI when moving icons to a selection and then all the previous icons automatically shift over. Would be very annoying to the user.
Hope this makes sense, if you need more details, comment below and I'll revise/update as needed.
While vuedraggable does not provide swapping by default https://github.com/SortableJS/Vue.Draggable/issues/466 , there's a great article that explains how to implement it yourself.
This is your modified code sandbox https://codesandbox.io/s/vuedraggable-with-css-grid-forked-wk4xk
Basically, you need to implement the swapping behaviour yourself by storing the current and future indexes (note, I changed the name of your list to "items" just to make it easier to port the code in the article).
<draggable v-model="items" :move="handleMove" #end="handleDragEnd">
In your script
methods: {
handleDragEnd() {
this.futureItem = this.items[this.futureIndex];
this.movingItem = this.items[this.movingIndex];
const _items = Object.assign([], this.items);
_items[this.futureIndex] = this.movingItem;
_items[this.movingIndex] = this.futureItem;
this.items = _items;
},
handleMove(e) {
const { index, futureIndex } = e.draggedContext;
this.movingIndex = index;
this.futureIndex = futureIndex;
return false; // disable sort
}
}

A-frame: get sphere from pool inside <a-videosphere> is Not visible

here the example what bind with Q
https://jsfiddle.net/91zcdm5r/1/
Exact problem: entity is adding from pool well, but it is not showing inside videsphere.
Looks like if videosphere have something like z-index 9999 , it is overlapping a-sphere entity. (not literally but looks like)
Think main reason because not possible to add a-sphere inside a-sphere?
Example:
AFRAME.registerComponent('mainvideo', {
init: function() {
//....
let intersection = this.raycaster.components.raycaster.getIntersection(this.el);
sphere.setAttribute('position', intersection.point)
console.log('sphere', sphere) //logs entity ok
//but it is not showing here
/* If try to add explit way like this:
// doc.querySelector('a-scene').appendChild(sphere)
//fall with core error
*/
})
What can be done here to showing entity a-sphere Visible.
Please check js fiddle forked from Piotr
https://jsfiddle.net/91zcdm5r/1/
ps: prev Q. binded with this here
How is properly to make pool with 10 <a-sphere>s A-frame
The spheres are too small to be seen. You can check it by either:
a) Change the <a-videosphere> radius from 900 to 100
b) Change the spheres scale from 0.1 0.1 0.1 to 5 5 5
Fiddle here (case b).

Don't understand train data from convnetjs

I'm trying to predict some data using a neural network in javascript. For that I found convnetjs that seems easy to use.
In the example, they use one thing that they call MagicNet, so you don't need to know about NN to work with it. This is the example of use:
// toy data: two data points, one of class 0 and other of class 1
var train_data = [new convnetjs.Vol([1.3, 0.5]), new convnetjs.Vol([0.1, 0.7])];
var train_labels = [0, 1];
// create a magic net
var magicNet = new convnetjs.MagicNet(train_data, train_labels);
magicNet.onFinishBatch(finishedBatch); // set a callback a finished evaluation of a batch of networks
// start training MagicNet. Every call trains all candidates in current batch on one example
setInterval(function(){ magicNet.step() }, 0});
// once at least one batch of candidates is evaluated on all folds we can do prediction!
function finishedBatch() {
// prediction example. xout is Vol of scores
// there is also predict_soft(), which returns the full score volume for all labels
var some_test_vol = new convnetjs.Vol([0.1, 0.2]);
var predicted_label = magicNet.predict(some_test_vol);
}
What I don't understand is this:
They create train data like [new convnetjs.Vol([1.3, 0.5]), new convnetjs.Vol([0.1, 0.7])] and then use 2 labels. Those labels, are one for each position of array or for each element of subarray in those positions??
Here is a visual example:
It's like [new 0, new 1] or like [new convnetjs.Vol([0, 1]), new convnetjs.Vol([0, 1])]?
The sample new convnetjs.Vol([1.3, 0.5]) has label 0.
The sample new convnetjs.Vol([0.1, 0.7]) has label 1.
In general, in machine learning, you'd usually have samples which can be quite high-dimensional (here they are only two-dimensional), but you'd have a single label per sample which tells you which "class" it belongs in. What the classes actually mean depends on the problem you are trying to solve; for instance, they could be the digits that are represented by images of hand-written digits.

calculate gantt chart total duration

I'm creating a gantt-like chart (configuration really) and need to calculate total duration and validate configurable durations. The goal is that users can build the gantt chart without knowing dates, but by knowing tasks and how they (loosely) relate. In a previous step, users add tasks and select start & end steps for those tasks. Steps have a fixed order. Actual dates are not known (or relevant) but will be mapped to steps later.
Most gantt tools I've seen rely on knowing the start/end dates and don't do calculations.
How should I calculate the total duration and also validate when a duration is invalid? Obviously in some cases a total can't be calculated: if there is an unused step between activities. A simple invalid duration would occur when 2 tasks share the same start and end date but have different values. A more complicated one would occur when 2 or more activities have different start/end steps and overlap.
I'm not looking for a complete solution (it would probably be of little use with my current code anyway), but more a general algorithm or approach. I would think a recursive solution would make sense, but because I'm doing this with JS/jQuery/DOM, I'm concerned about performance of a recursive solution that has to repeatedly look up elements. Should I start calculating from the end or the beginning? should I follow each step's start/end until I go no further or re-evaluate which step to add to total duration mid-way through?
Here is a picture of the current markup:
I'll try to explain what I wound up doing.
I think to follow you have to know a bit about the requirements.
This interactive/configurable gantt/schedule is being used as a template to estimate production timelines.
There are 3 pieces:
Steps
Activities
Durations of activities, which are different depending on the type of item the schedule is applied to.
Since this is a template used for estimation, initially there are no dates - just arbitrary durations tied to activities mapped to steps. However eventually steps get mapped to dates from an imported report (or manually entered).
There are 3 pages where the user incrementally builds up the schedule:
Add/Edit Steps: Steps are rows which are created with a sort order value (inferred)
Add/Edit Activities: A matrix with Steps as columns, Activities as rows. Every intersection is a checkbox. A Start and End Step must be selected for each Activity.
Add/Edit Durations: An item type is selected and durations are added for each activity.
Classes
Step [ Name, StepOrder, ..]
Activity [ Name, StartStepID, StartStepOrder, EndStepID, EndStepOrder, ..]
ActivityDuration : Activity [ Duration, ItemType, ..]
In MVC Controller/Repository:
// start by ordering the durations by the order of the steps
var sortedActivities = durations
.OrderBy(x => x.StartStepOrder)
.ThenBy(x => x.EndStepOrder);
// create func to get the path name from the old + new activity
var getActivityPath = new Func<string, string, string>(
(prevPath, activityID) =>
{
return string.IsNullOrEmpty(prevPath)
? string.Format("{0}", activityID)
: string.Format("{0}.{1}", prevPath, activityID);
});
// create the recursive func we'll call to do all the work
Action<List<ActivityDuration>, string, long?, IEnumerable<ActivityDuration>> buildPaths = null;
buildPaths = (activities, path, startStepID, starts) =>
{
// activities will be null until we are joining gapped paths,
// so grab the activities with the provided startStepID
if (starts == null)
starts = activities.Where(x => x.StartStepID == startStepID);
// each activity represents a new branch in the path
foreach (var activity in starts)
{
var newPath = getActivityPath(path, activity.Id.ToString());
// add the new path and it's ordered collection
// of activities to the collection
if (string.IsNullOrEmpty(path))
{
paths.Add(newPath, new ActivityDuration[] { activity });
}
else
{
paths.Add(newPath, paths[path].Concat(new ActivityDuration[] { activity }));
}
// do this recursively providing the EndStepID as the new Start
buildPaths(activities, newPath, activity.EndStepID, null);
}
// if there were any new branches, remove the previous
// path from the collection
if (starts.Any() && !string.IsNullOrEmpty(path))
{
paths.Remove(path);
}
};
// since the activities are in step order, the first activity's
// StartStepID will be where all paths start.
var firstStepID = sortedActivities.FirstOrDefault().StartStepID;
// call the recursive function starting with the first step
buildPaths(sortedActivities.ToList(), null, firstStepID, null);
// handle gaps in the paths after all the first connected ones have been pathed.
// :: ie - step 1,2 & 4,5 are mapped, but not step 3
// these would be appended to the longest path with a step order < start step of the gapped activity's start step (!!!)
// :: ie - the path should be 1-2,2-4,4-5)
// because the list of paths can grow, we need to keep track of the count
// and loop until there are no more paths added
var beforeCount = paths.Count;
var afterCount = beforeCount + 1;
while (beforeCount < afterCount)
{
foreach (var path in paths.ToArray())
{
var lastActivity = path.Value.Last();
// check for activities that start after the last one in each path ..
// .. that don't start on another activity's end step (because that would be a part of a path already)
var gapped = sortedActivities
.Where(x => x.StartStepOrder > lastActivity.EndStepOrder)
.Where(thisAct =>
!sortedActivities
.Select(otherAct => otherAct.EndStepID)
.Contains(thisAct.StartStepID)
);
beforeCount = paths.Count;
// for each new gapped path, build paths as if it was specified by the previous activity
buildPaths(sortedActivities.ToList(), path.Key, null, gapped);
afterCount = paths.Count;
}
}
// build up an object that can be returned to
// JS with summations and ordering already done.
rValue = new ActivityPaths()
{
Paths = paths
.Select(x => new ActivityPath()
{
Path = x.Key,
ActivityDurations = x.Value,
TotalDuration = x.Value.Sum(y => y.Duration)
})
.OrderByDescending(x => x.TotalDuration)
};
There are admittedly some shortcomings of this design, but the use cases allow for it. Specifically:
- An activity can't directly have more than one dependent step - or in other words - 2 steps can't have the same step order.
- If 2 paths have the same total duration, only one will show as the critical path.
Since the dates which are mapped to steps are ultimately used to calculate back/forward to the end of a path from a given point of time, this is OK. Once all dates are provided, a more accurate critical path can be calculated if needed.
The entire set of paths is returned so that some validation can be implemented in the javascript. The first path will be the critical 'one', and this path gets highlighted in the UI, with the total duration of the critical path shown as well:

KineticJS apply multiple filters to the image and I saw a hue-filter also

Since filters are poorly documented in the kineticJS I have a problem applying two filters to a image. Couple of questions:
1)
I want to set Blur and Brighten filters to the same image.
Both works separetely:
if (!!image.getAttr('filterBrightness')) {
image.setFilter(Kinetic.Filters.Brighten);
}
image.setFilterBrightness(120);
and
if (!!image.getAttr('filterAmount')){
image.setFilter(Kinetic.Filters.Blur);
}
image.setFilterRadius(2);
I tried
image.applyFilter(Kinetic.Filters.Blur)
image.setFilterAmount(2);
and it worked but again when reapplyin another filter, the blur filter went off.
2) How do I correctly check if there is a filter set? I tried getFilter() function but firebug's console.log only shows "function".
3) There is some ShiftHue-filter, but obviously I don't understand a word from the source. See: http://kineticjs.com/docs/Kinetic.Filters.html and the source (http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.0.js) says as below. What I don't understand is "set hue shift amount #name setFilterBrightness" is it a mistake in the source documentation?
How to use that filter? Set filter
/**
* get hue shift amount. The shift amount is a number between 0 and 360.
* #name getFilterBrightness
* #method
* #memberof Kinetic.Image.prototype
*/
/**
* set hue shift amount
* #name setFilterBrightness
* #method
* #memberof Kinetic.Image.prototype
*/
Thank you!
1. At this point, I believe you can only apply 1 filter at once.
But you can use myImage.setFilter to change to a different kind of filter
I just took a look at Kinetic's source code for images:
https://github.com/ericdrowell/KineticJS/blob/master/src/shapes/Image.js
Line 114 defines an image's applyFilter method.
That method doesn't iterate through a series of filters, just one filter.call.
So no multiple filters for now.
I also see in the issues section there is a request for multiple filters that's categorized as an "enhancement" (meaning not yet available).
https://github.com/ericdrowell/KineticJS/issues/548
For now, if you want multiple filters you'll have to add an image manipulation plugin to your project.
2. Checking if a filter is already set
Internally, image.clearFilter works like this:
clearFilter: function() {
this.filterCanvas = null;
this._applyFilter = false;
}
So you should be able to check if filterCanvas is null or _applyFilter==false;
3. Changing Hue
There is a pixelShiftHue method in colorPack.js that:
Converts a pixel color to HSL,
Shifts the hue by a specified degree
Coverts the color back to RGB
Returns the R,G,B values of the converted color
That method is used in the brighten filter, but it's not implemented as its own filter.
Of course, you could use the code to do hue shifting yourself.
https://github.com/ericdrowell/KineticJS/blob/355c80088f396e21f412eb743620f3c70ff39023/src/filters/ColorPack.js
markE's answer is correct in saying that there is no out of the box way to add multiple filters to an image yet.
But there is a workaround:
Create a Kinetic Image
Add a single filter to it
Use toDataURL() on the first Kinetic image, to grab the image data
Create a second Kinetic Image with the dataURL from step 3
Add a new filter to the image created in step 4
Here's an example based off of the 2 html5canvastutorials:
Filter Tutorial: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-invert-image-tutorial/
and
toDataURL() tutorial: http://www.html5canvastutorials.com/kineticjs/html5-canvas-stage-data-url-with-kineticjs/
var imageObj = new Image();
imageObj.onload = function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 300
});
var layer = new Kinetic.Layer();
//Step 1
darth = new Kinetic.Image({
x: 10,
y: 10,
image: imageObj,
draggable: true,
filter: Kinetic.Filters.Grayscale, //Step 2
filterRadius: 20
});
layer.add(darth);
stage.add(layer);
//Step 3
var filteredDarthURL = darth.toDataURL();
var imageObj2 = new Image();
imageObj2.onload = function() {
//Step 4
var doubleFilteredDarth = new Kinetic.Image({
x: 10,
y: 10,
image: imageObj2,
draggable: true,
filter: Kinetic.Filters.Blur, //Step 5
filterRadius: 20
});
darth.destroy(); //or darth.remove() or darth.hide()
layer.add(doubleFilteredDarth);
layer.draw();
}
imageObj2.src = filteredDarthURL;
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
Unfortunately I can't post a JSFiddle because of the Security error for trying to use toDataURL() on JSfiddle. But you can test it on your localhost and try it out for yourself. Works okay as an alternative, without having to use another external library to process your images.
KineticJS >= 5.0
imgs.filters([Kinetic.Filters.Grayscale, Kinetic.Filters.Brighten, Kinetic.Filters.Sepia]);
imgs.brightness(-0.1);
imgs.noise(0.8);

Categories