Skip to content

Commit

Permalink
Merge development into main (#1655)
Browse files Browse the repository at this point in the history
* Don't allow user to remove question if it is being used in a rule (#1647)

* Return to previous answer in case the rule fails (#1646)

* Hotfix: Removing date default values for image collection (#1649)

* Changing text for user assignments (#1651)

* COL-520: Fix incorrect plot sizes (#1652)

* Changing text language for uploading plot and sample details. (#1653)
  • Loading branch information
a-luz authored Aug 10, 2023
1 parent 17cdad5 commit 35a450a
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 38 deletions.
50 changes: 29 additions & 21 deletions src/clj/collect_earth_online/generators/clj_point.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
(:require [triangulum.type-conversion :as tc]
[triangulum.database :refer [call-sql]]
[collect-earth-online.utils.project :refer [check-plot-limits check-sample-limits]]
[collect-earth-online.utils.geom :refer [make-wkt-point EPSG:3857->4326 EPSG:4326->3857]]
[collect-earth-online.utils.geom :refer [make-wkt-point
EPSG:3857->4326
EPSG:4326->3857
epsg3857-point-resolution]]
[collect-earth-online.utils.part-utils :refer [init-throw]]))

;;; Helpers
Expand Down Expand Up @@ -122,29 +125,34 @@
sample-distribution
samples-per-plot
sample-resolution]
(let [circle? (= plot-shape "circle")
radius (/ plot-size 2.0)
buffer (/ radius 25.0)
samples-per-plot (case sample-distribution
"gridded" (count (create-gridded-sample-set
circle?
45
45
radius
buffer
sample-resolution))
"random" samples-per-plot
"center" 1.0
"none" 1.0)]
(let [circle? (= plot-shape "circle")
{:keys [lon lat]} (first plots)
correction-factor (epsg3857-point-resolution (EPSG:4326->3857 [lon lat]))
radius (/ plot-size 2.0 correction-factor)
buffer (/ radius 25.0 correction-factor)
samples-per-plot (case sample-distribution
"gridded" (count (create-gridded-sample-set
circle?
45
45
radius
buffer
sample-resolution))
"random" samples-per-plot
"center" 1.0
"none" 1.0)]
(check-sample-limits (* plot-count samples-per-plot)
50000.0
samples-per-plot
200.0)
(mapcat (fn [{:keys [plot_id visible_id lon lat]}]
(let [[center-x center-y] (EPSG:4326->3857 [lon lat])
visible-offset (-> (dec visible_id)
(* samples-per-plot)
(inc))]
(let [[center-x center-y] (EPSG:4326->3857 [lon lat])
visible-offset (-> (dec visible_id)
(* samples-per-plot)
(inc))
plot-correction-factor (epsg3857-point-resolution [center-x center-y])
plot-radius (/ plot-size 2.0 plot-correction-factor)
plot-sample-resolution (/ sample-resolution plot-correction-factor)]
(map-indexed (fn [idx [sample-lon sample-lat]]
{:plot_rid plot_id
:visible_id (+ idx visible-offset)
Expand All @@ -154,10 +162,10 @@
[[lon lat]]

(= "gridded" sample-distribution)
(create-gridded-sample-set circle? center-x center-y radius buffer sample-resolution)
(create-gridded-sample-set circle? center-x center-y plot-radius buffer plot-sample-resolution)

(= "random" sample-distribution)
(create-random-sample-set circle? center-x center-y radius buffer samples-per-plot)
(create-random-sample-set circle? center-x center-y plot-radius buffer samples-per-plot)

:else []))))
plots)))
Expand Down
10 changes: 8 additions & 2 deletions src/clj/collect_earth_online/utils/geom.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

;;; GeoJSON

(def wsg84-radius 6378136.98)

(defn make-wkt-point [lon lat]
(format "POINT(%s %s)" lon lat))

Expand All @@ -20,7 +22,7 @@
[& points]
(let [points (mapv (fn [[lon lat]]
[(* lon 111319.490778)
(-> lat (+ 90.0) (/ 360.0) (* Math/PI) (Math/tan) (Math/log) (* 6378136.98))])
(-> lat (+ 90.0) (/ 360.0) (* Math/PI) (Math/tan) (Math/log) (* wsg84-radius))])
points)]
(if (= 1 (count points))
(first points)
Expand All @@ -31,8 +33,12 @@
[& points]
(let [points (mapv (fn [[x y]]
[(/ x 111319.490778)
(-> y (/ 6378136.98) (Math/exp) (Math/atan) (/ Math/PI) (* 360.0) (- 90.0))])
(-> y (/ wsg84-radius) (Math/exp) (Math/atan) (/ Math/PI) (* 360.0) (- 90.0))])
points)]
(if (= 1 (count points))
(first points)
points)))

(defn epsg3857-point-resolution
[point]
(/ 1 (Math/cosh (/ (second point) wsg84-radius))))
2 changes: 1 addition & 1 deletion src/js/project/AssignPlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export default class AssignPlots extends React.Component {
{userMethod === "equal" && users.length > 0 && (
<p className="font-italic ml-2 mt-2 small">
{["shp", "csv"].includes(plotDistribution)
? "- Unable to estimate assignments for external files."
? "- CEO will use the file plot distribution information for plot assignment."
: `- Each user will be assigned ~${formatNumberWithCommas(
Math.round(totalPlots / users.length)
)} plots.`}
Expand Down
4 changes: 2 additions & 2 deletions src/js/project/PlotDesign.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,13 @@ export class PlotDesign extends React.Component {
csv: {
display: "CSV File",
description:
"Specify your own plot centers by uploading a CSV with these fields: LON,LAT,PLOTID.",
"Specify your own plot centers by uploading a CSV with these fields: LON,LAT,PLOTID. Each plot center must have a unique PLOTID value.",
layout: this.renderCSV(),
},
shp: {
display: "SHP File",
description:
"Specify your own plot boundaries by uploading a zipped Shapefile (containing SHP, SHX, DBF, and PRJ files) of polygon features. Each feature must have a unique PLOTID field.",
"Specify your own plot boundaries by uploading a zipped Shapefile (containing SHP, SHX, DBF, and PRJ files) of polygon features. Each feature must have a unique PLOTID value.",
layout: this.renderFileInput("shp"),
},
};
Expand Down
4 changes: 2 additions & 2 deletions src/js/project/SampleDesign.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,14 @@ export class SampleDesign extends React.Component {
csv: {
display: "CSV File",
description:
"Specify your own sample points by uploading a CSV with these fields: LON,LAT,PLOTID,SAMPLEID.",
"Specify your own sample points by uploading a CSV with these fields: LON,LAT,PLOTID,SAMPLEID. Each feature must have PLOTID and SAMPLEID fields. Each sample within a unique plot must have a unique SAMPLEID.",
layout: this.renderFileInput("csv"),
disabled: !["csv", "shp"].includes(plotDistribution),
},
shp: {
display: "SHP File",
description:
"Specify your own sample shapes by uploading a zipped Shapefile (containing SHP, SHX, DBF, and PRJ files) of polygon features. Each feature must have PLOTID and SAMPLEID fields.",
"Specify your own sample shapes by uploading a zipped Shapefile (containing SHP, SHX, DBF, and PRJ files) of polygon features. Each feature must have PLOTID and SAMPLEID fields. Each sample within a unique plot must have a unique SAMPLEID.",
layout: this.renderFileInput("shp"),
disabled: !["csv", "shp"].includes(plotDistribution),
},
Expand Down
6 changes: 6 additions & 0 deletions src/js/survey/AnswerDesigner.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export default class AnswerDesigner extends React.Component {
removeAnswer = () => {
const { surveyQuestionId, answerId } = this.props;
const { surveyQuestions, setProjectDetails } = this.context;
const answerHasRule = this.answerRule(surveyQuestionId, parseInt(answerId));
if (answerHasRule) {
alert(
"This answer is being used in a rule. Please either delete or update the rule before removing the answer.");
return null;
}
const matchingQuestion = findObject(
surveyQuestions,
([_id, sq]) =>
Expand Down
3 changes: 2 additions & 1 deletion src/js/survey/SurveyCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,10 @@ export default class SurveyCollection extends React.Component {
);
};

validateAndSetCurrentValue = (questionIdToSet, answerId, answerText = null) => {
validateAndSetCurrentValue = (questionIdToSet, answerId, answerText = null, previousAnswer = null) => {
const ruleError = this.rulesViolated(questionIdToSet, answerId, answerText);
if (ruleError) {
this.props.setCurrentValue(questionIdToSet, answerId, previousAnswer);
alert(ruleError);
} else {
this.props.setCurrentValue(questionIdToSet, answerId, answerText);
Expand Down
18 changes: 14 additions & 4 deletions src/js/survey/SurveyCollectionAnswers.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,22 @@ class AnswerInput extends React.Component {

resetInputText = () => {
const answerId = Number(firstEntry(this.props.surveyNode.answers)[0]);
const answerText = this.props.surveyNode.answered[0]?.answerText;
const allSamplesMatch = this.props.surveyNode.answered.every(
(a) => {
return (a.answerId === answerId && (a.answerText === answerText && a.answerText != undefined))}
);
const matchingNode = this.props.surveyNode.answered.find(
(a) => a.answerId === answerId && a.sampleId === this.props.selectedSampleId
);
this.setState({
newInput: matchingNode ? matchingNode.answerText : "",
});
if(allSamplesMatch) {
this.setState ({
newInput: this.props.surveyNode.answered[0] ? answerText : ""});
} else {
this.setState({
newInput: matchingNode ? matchingNode.answerText : ""
});
}
};

updateInputValue = (value) => this.setState({ newInput: value });
Expand Down Expand Up @@ -167,7 +177,7 @@ class AnswerInput extends React.Component {
name="save-input"
onClick={() => {
if (!answer.required || newInput || newInput === 0) {
validateAndSetCurrentValue(surveyNodeId, answerId, newInput);
validateAndSetCurrentValue(surveyNodeId, answerId, newInput, answer.answer);
}
}}
style={{ height: "2.5rem" }}
Expand Down
9 changes: 8 additions & 1 deletion src/js/survey/SurveyDesignQuestion.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export default function SurveyDesignQuestion({ indentLevel, editMode, surveyQues

const removeQuestion = () => {
const childQuestionIds = getChildQuestionIds(surveyQuestionId);
const questionHasRules = checkQuestionRules(surveyQuestionId);
if(questionHasRules) {
alert("This question is being used in a rule. Please either delete or update the rule before removing the question");
return null;
}
const newSurveyQuestions = filterObject(
surveyQuestions,
([sqId]) => !childQuestionIds.includes(Number(sqId))
Expand All @@ -61,7 +66,9 @@ export default function SurveyDesignQuestion({ indentLevel, editMode, surveyQues
(rl.questionId1 === questionId ||
rl.questionId2 === questionId) ||
// Rules for Sums of answers
(rl.questionIds?.includes(questionId))
(rl.questionIds?.includes(questionId)) ||
// Rules for Regex Matching or Number Range
(rl.questionId === questionId)
));
return matchingRule;
}
Expand Down
10 changes: 6 additions & 4 deletions src/js/utils/mercator.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { GeoJSON, KML } from "ol/format";
import { Tile as TileLayer, Vector as VectorLayer, Group as LayerGroup } from "ol/layer";
import { BingMaps, Cluster, OSM, TileWMS, Vector as VectorSource, XYZ } from "ol/source";
import { Circle as CircleStyle, Fill, Stroke, Style, Text as StyleText } from "ol/style";
import { fromLonLat, transform, transformExtent } from "ol/proj";
import { fromLonLat, transform, transformExtent, getPointResolution } from "ol/proj";
import { fromExtent, fromCircle } from "ol/geom/Polygon";
import { getArea } from "ol/sphere";
import { formatDateISO, isNumber } from "./generalUtils";
Expand Down Expand Up @@ -988,13 +988,15 @@ mercator.geometryToGeoJSON = (geometry, toProjection, fromProjection = null, dec
});
};


// [Pure] Returns a polygon geometry matching the passed in parameters.
mercator.getPlotPolygon = (center, size, shape) => {
const [centerX, centerY] = mercator.parseGeoJson(center, true).getCoordinates();
const radius = size / 2;
const radius = (size / 2) / (getPointResolution('EPSG:3857', 1, [centerX, centerY]));

return shape === "circle"
? new Circle([centerX, centerY], radius)
: fromExtent([centerX - radius, centerY - radius, centerX + radius, centerY + radius]);
? new Circle(center, radius)
: fromExtent([centerX - radius, centerY - radius, centerX + radius, centerY + radius])
};

// [Pure] Returns a new vector source containing the passed in plots.
Expand Down

0 comments on commit 35a450a

Please sign in to comment.