Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Digitizing tools #377

Merged
merged 24 commits into from Feb 1, 2018
Merged

Digitizing tools #377

merged 24 commits into from Feb 1, 2018

Conversation

annarieger
Copy link
Member

@annarieger annarieger commented Jan 30, 2018

FEATURE

Description:

This MR introduces the basic digitizing tools to draw, select, modify and delete vector features on/from the map.

The following tools are supported at the moment:

  • draw point
  • draw linestring
  • draw polygon
  • draw labeled point
  • draw circle
  • draw polygon
  • select and modify feature
  • select and delete feature
  • select and copy feature

Please review @terrestris/devs

Copy link
Member

@marcjansen marcjansen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice work so far. Looking forward to checking this again once you consider it no longer WIP.

---
layout: basic.hbs
title: RedliningButton example
description: This is a example showing an RedliningButton.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…many redlining buttons

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in 97f906e

});
});

describe('#Static methods', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These aren't statics, are they?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they're not, fixed in 3a0a656


const mockInteraction = getMockDrawPointInteraction();

const defaultMapInteractionsLength = map.getInteractions().getArray().length;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or map.getInteractions().getLength();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 3a0a656

interaction: [mockInteraction]
});

expect(map.getInteractions().getArray().length).toBe(defaultMapInteractionsLength + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 3a0a656

map.addInteraction(mockInteraction);
instance._redliningFeatures.on('add', wrapper.instance().handleTextAdding);

expect(instance._redliningFeatures.listeners_.add.length).toBe(2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the lines below where we use the private property .listeners_ are a bit fragile. Right now I don't have an alternative, but at least a comment would be nice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment added in 3a0a656


instance.onToggle(false);

expect(instance._selectInteraction.listeners_select).toBeUndefined();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this bbe instance._selectInteraction.listeners.select_? Is this just stubbed right now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, nice catch.. fixed in 3a0a656


instance.onToggle(false);

expect(instance._selectInteraction.listeners_select).toBeUndefined();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one another nice catch :) fixed in 3a0a656

*
* @class DigitizeUtil
*/
class DigitizeUtil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a more appropriate name be FeatureUtil?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to AnimateUtil in 0504b8e. I think it's even more meaningful as FeatureUtil

vectorContext.setFillStrokeStyle(
style.getFill(), style.getStroke());
vectorContext.setImageStyle(style.getImage());
if (geometry instanceof ol.geom.Point) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below:

Should we import the ol/geom/Point and use thes in the instanceof checks?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, indeed! And could you please remove the ol entry from the eslint globals (see .eslintrc)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.eslintrc adapted in 4a17d2a, imports fixed in 4a1ea1e

@marcjansen
Copy link
Member

I have adressed some minor comments in annarieger#1, you decide if you want to have these.

* @extends React.Component
*
*/
class RedliningButton extends React.Component {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not technical, but could we please get rid of the term Redlining (see here).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since 938d625 the class is renamed to DigitizeButton

this.createDrawInteraction(pressed);
} else if (editType) {
this.createSelectOrModifyInteraction(pressed);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Empty line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 08a4ce5


this.state = {
redliningLayer: null,
interaction: null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name is misleading as it contains an array of interactions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're so right, renamed it in d9df6bd

}),
stroke: new OlStyleStroke({
color: !useSelectStyle ? strokeColor : selectStrokeColor,
width: 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and some other style properties aren't configurable yet. Do you have any attempt to make them configurable, e.g. by passing an ol.Style for each draw type as prop?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, please make these cinfigurable

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue -> #380

Will be done in one of follow-ups 😇

let geometryFunction;
let type = drawType;

if (drawType === 'Rectangle') {
Copy link
Member

@dnlkoch dnlkoch Jan 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Please move all draw and edit type strings to statics.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in df4e3fd

* Creates a correctly configured OL select and/or modify and/or translate
* interaction(s) depending on given editType and adds this/these to the map.
*
* @method
Copy link
Member

@dnlkoch dnlkoch Jan 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, but is the @method tag needed here for jsdoc?

this._selectInteraction = new OlInteractionSelect({
condition: OlEventsCondition.singleClick,
style: this.getRedliningStyleFunction,
hitTolerance: 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Should be configurable.

Copy link
Member Author

@annarieger annarieger Feb 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue -> #380

Will be done in one of follow-ups 😇

features: this._selectInteraction.getFeatures(),
deleteCondition: OlEventsCondition.singleClick,
style: this.getRedliningStyleFunction,
pixelTolerance: 10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: The default value is not in sync with the hitTolerance of the select interaction and should be configurable as well.

Copy link
Member Author

@annarieger annarieger Feb 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue -> #380

Will be done in one of follow-ups 😇

map.on('pointermove', this.onPointerMove);

this.setState({
interaction: interactions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a need for checking the pressed state of the button in callback (like in the createDrawInteraction())?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, no check needed here

const feat = evt.selected[0];
const copy = feat.clone();
//eslint-disable-next-line
const doneFn = finalFeature => {this._redliningFeatures.push(finalFeature)};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely minor: Missing colon behind this._redliningFeatures.push(finalFeature).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 08a4ce5

this.setState({
textLabel: ''
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Empty line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 08a4ce5

*
* @method
*/
setTextOnFeature = (feat) => {
Copy link
Member

@dnlkoch dnlkoch Jan 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parentheses can be omitted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 08a4ce5


const { map } = this.props;
const pixel = map.getEventPixel(evt.originalEvent);
const hit = map.hasFeatureAtPixel(pixel);
Copy link
Member

@dnlkoch dnlkoch Jan 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure here, but we may want to include a (customizable) layerFilter to only change the cursor for features/layers available to edit with the given interactions.

Copy link
Member Author

@annarieger annarieger Feb 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue -> #380

Will be done in one of follow-ups 😇

: this.className;

return (
<div className="wrapper">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try to set the render children as an array like:

return([
  <ToggleButton>,
  <Modal>
    <Input />
  </Modal>
]);

This way it might be possible to avoid the usage of the wrapper div.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've tried it out together with @KaiVolland and we think it would be better to leave this without changes here

}
}

.wrapper {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the wrapper can't be avoided, please rename to react-geo-redlining-button-wrapper or similar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 08a4ce5

* in the end with given `duration` in ms, using the given style,
* calling a `doneFn`.
*
* @param {OlMap} map An OlMap.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OlMap -> ol.Map

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get in sync with the ol API and to harmonize with the method documentation overall. But it's still non-blocking…

Copy link
Member

@KaiVolland KaiVolland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://i.imgur.com/acIf8q9.gif

Very nice work.

Added some remarks you might want to tackle.

I think we should get rid of the name redlining as @dnlkoch mentioned.

* @type {OlFeature}
* @private
*/
_redliningTextFeature = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the indention correct? Hard to see in the diff view but it seems like 3 instead of 2 spaces…

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 08a4ce5


super(props);

if (!this.props.drawType && !this.props.editType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may wan't to use a custom proptype validator instead: https://reactjs.org/docs/typechecking-with-proptypes.html

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to leave this check as is cause of using of oneOf check for both props drawType and editType

*
* @method
*/
getRedliningStyleFunction = feature => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it needed that we can pass the style(s) from outside as a prop?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an issue -> #380

Will be done in one of follow-ups 😇

onFeatureCopy = evt => {
const feat = evt.selected[0];
const copy = feat.clone();
//eslint-disable-next-line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you disable eslint here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of using of inline function in the next line which needs JS Doc comment

const pixel = map.getEventPixel(evt.originalEvent);
const hit = map.hasFeatureAtPixel(pixel);

map.getTargetElement().style.cursor = hit ? 'pointer' : '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor: cursor could be move (or grab and grabbing) for move interaction. Maybe there are some more semantic cursors for the different controls.
Compare: https://developer.mozilla.org/de/docs/Web/CSS/cursor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's no needed cause ol.interaction.Modify and ol.interaction.Translate already provides the appropriate cursors as soon as interaction was activated

import OlGeomLineString from 'ol/geom/linestring';
import OlGeomPolygon from 'ol/geom/polygon';
// import OlOverlay from 'ol/overlay';
// import OlObservable from 'ol/observable';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plz remove if not used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in 3a0a656

const deltaX = totalDisplacement / expectedFrames;
const deltaY = totalDisplacement / expectedFrames;

//eslint-disable-next-line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you disable es lint here?

*
* @return {String} A listener key from a postcompose event.
*/
static moveFeature = (map, featureToMove, duration, pixel, style, doneFn) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to return a Promise instead of passing a callback function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in 0504b8e

---
layout: basic.hbs
title: DigitizeButton example
description: This is a example showing digitize buttons with different interactions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviews guys 🍍

Everything is fixed, I'll merge now

@annarieger annarieger changed the title WIP Redlining tools Digitize tools Feb 1, 2018
@annarieger annarieger merged commit 29c4443 into terrestris:master Feb 1, 2018
@annarieger annarieger changed the title Digitize tools Digitizing tools Feb 1, 2018
@annarieger annarieger deleted the redlining-tools branch February 1, 2018 14:11
@marcjansen
Copy link
Member

Nice work, everyone. Thanks

@KaiVolland KaiVolland mentioned this pull request Feb 2, 2018
56 tasks
hblitza pushed a commit that referenced this pull request Oct 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants