From 8e50e2c0a25cf294f8d2633a193e57d536500220 Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Tue, 26 Sep 2023 07:30:16 -0700 Subject: [PATCH 1/3] Updated docs for on --- docs/reference/specifiers.rst | 11 ++++++----- docs/syntax_guide.rst | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/reference/specifiers.rst b/docs/reference/specifiers.rst index 6dc4d42b6..21c997e21 100644 --- a/docs/reference/specifiers.rst +++ b/docs/reference/specifiers.rst @@ -98,10 +98,11 @@ contained in *region* Like :sampref:`in {region}`, but also enforces that the object be entirely contained in the given `Region`. .. _on {region}: +.. _on ({region} | {Object} | {vector}): .. _on: -on *region* ------------ +on (*region* | *Object* | *vector*) +----------------------------------- **Specifies**: @@ -110,12 +111,12 @@ on *region* **Dependencies**: :prop:`baseOffset` • :prop:`contactTolerance` • :prop:`onDirection` -If :prop:`position` is not already specified with priority 1, positions the *base* of the object uniformly at random in the given `Region`, offset by :prop:`contactTolerance` (to avoid a collision). +If :prop:`position` is not already specified with priority 1, positions the *base* of the object uniformly at random in the given `Region`, on the :prop:`onSurface` of the given `Object`, or with the base of the object at the given vector. The position is always offset by half of :prop:`contactTolerance` (to avoid a collision). The base of the object is determined by adding the object's :prop:`baseOffset` to its :prop:`position`. -Note that while :specifier:`on` can be used with `Region`, `Object` and `Vector`, it cannot be used with a distribution containing anything other than `Region`. When used with an object the base of the object being placed is placed on the target object's `onSurface` and when used with a vector the base of the object being placed is set to that position. +Note that while :specifier:`on` can be used with `Region`, `Object` and `Vector`, it cannot be used with a distribution containing anything other than `Region`. -If instead :prop:`position` has already been specified with priority 1, then its value is modified by projecting it onto the given region. +If instead :prop:`position` has already been specified with priority 1, then its value is modified by projecting it onto the given region. Not that this modifying version of the specifier does not accept a vector. More precisely, we find the closest point in the region along :prop:`onDirection` (or its negation [1]_), and place the base of the object at that point. If :prop:`onDirection` is not specified, a default value is inferred from the region. A region can either specify a default value to be used, or for volumes straight up is used and for surfaces the mean of the face normal values is used (weighted by the area of the faces). If the region has a :term:`preferred orientation` (a vector field), :prop:`parentOrientation` is specified to be equal to that orientation at the object’s :prop:`position` (whether or not this specifier is being used as a modifying specifier). diff --git a/docs/syntax_guide.rst b/docs/syntax_guide.rst index 6ed669cbe..8f7a61448 100644 --- a/docs/syntax_guide.rst +++ b/docs/syntax_guide.rst @@ -208,7 +208,7 @@ Additional specifiers for the :prop:`position` and :prop:`orientation` propertie - Positions the object uniformly at random in the given Region * - :sampref:`contained in {region}` - Positions the object uniformly at random entirely contained in the given Region - * - :sampref:`on {region}` + * - :sampref:`on ({region} | {Object} | {vector})` - Positions the base of the object uniformly at random in the given Region, or modifies the position so that the base is in the Region. * - :sampref:`offset by {vector}` - Positions the object at the given coordinates in the local coordinate system of ego (which must already be defined) From 42b2370ec2799c030c51d9e8bab049291f43206e Mon Sep 17 00:00:00 2001 From: Eric Vin <8935814+Eric-Vin@users.noreply.github.com> Date: Sat, 30 Sep 2023 18:12:57 -0700 Subject: [PATCH 2/3] Update docs/reference/specifiers.rst Co-authored-by: Daniel Fremont --- docs/reference/specifiers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/specifiers.rst b/docs/reference/specifiers.rst index 21c997e21..4cd605eba 100644 --- a/docs/reference/specifiers.rst +++ b/docs/reference/specifiers.rst @@ -116,7 +116,7 @@ The base of the object is determined by adding the object's :prop:`baseOffset` t Note that while :specifier:`on` can be used with `Region`, `Object` and `Vector`, it cannot be used with a distribution containing anything other than `Region`. -If instead :prop:`position` has already been specified with priority 1, then its value is modified by projecting it onto the given region. Not that this modifying version of the specifier does not accept a vector. +If instead :prop:`position` has already been specified with priority 1, then its value is modified by projecting it onto the given region (or the :prop:`onSurface` of the given object). Note that this modifying version of the specifier does not accept a vector. More precisely, we find the closest point in the region along :prop:`onDirection` (or its negation [1]_), and place the base of the object at that point. If :prop:`onDirection` is not specified, a default value is inferred from the region. A region can either specify a default value to be used, or for volumes straight up is used and for surfaces the mean of the face normal values is used (weighted by the area of the faces). If the region has a :term:`preferred orientation` (a vector field), :prop:`parentOrientation` is specified to be equal to that orientation at the object’s :prop:`position` (whether or not this specifier is being used as a modifying specifier). From 7c5db2d62c5db5ade5744fd509a2d82ccdc0dea0 Mon Sep 17 00:00:00 2001 From: Eric Vin Date: Mon, 2 Oct 2023 14:19:30 -0700 Subject: [PATCH 3/3] Updated On Typechecking + Docs. --- docs/reference/specifiers.rst | 4 ++-- docs/syntax_guide.rst | 6 ++++-- src/scenic/core/type_support.py | 4 ++-- src/scenic/syntax/veneer.py | 10 +++++----- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/reference/specifiers.rst b/docs/reference/specifiers.rst index 4cd605eba..83f99f74c 100644 --- a/docs/reference/specifiers.rst +++ b/docs/reference/specifiers.rst @@ -98,7 +98,9 @@ contained in *region* Like :sampref:`in {region}`, but also enforces that the object be entirely contained in the given `Region`. .. _on {region}: +.. _on ({region} | {Object}): .. _on ({region} | {Object} | {vector}): +.. _on {vector}: .. _on: on (*region* | *Object* | *vector*) @@ -114,8 +116,6 @@ on (*region* | *Object* | *vector*) If :prop:`position` is not already specified with priority 1, positions the *base* of the object uniformly at random in the given `Region`, on the :prop:`onSurface` of the given `Object`, or with the base of the object at the given vector. The position is always offset by half of :prop:`contactTolerance` (to avoid a collision). The base of the object is determined by adding the object's :prop:`baseOffset` to its :prop:`position`. -Note that while :specifier:`on` can be used with `Region`, `Object` and `Vector`, it cannot be used with a distribution containing anything other than `Region`. - If instead :prop:`position` has already been specified with priority 1, then its value is modified by projecting it onto the given region (or the :prop:`onSurface` of the given object). Note that this modifying version of the specifier does not accept a vector. More precisely, we find the closest point in the region along :prop:`onDirection` (or its negation [1]_), and place the base of the object at that point. If :prop:`onDirection` is not specified, a default value is inferred from the region. A region can either specify a default value to be used, or for volumes straight up is used and for surfaces the mean of the face normal values is used (weighted by the area of the faces). diff --git a/docs/syntax_guide.rst b/docs/syntax_guide.rst index 8f7a61448..c376ad450 100644 --- a/docs/syntax_guide.rst +++ b/docs/syntax_guide.rst @@ -208,8 +208,10 @@ Additional specifiers for the :prop:`position` and :prop:`orientation` propertie - Positions the object uniformly at random in the given Region * - :sampref:`contained in {region}` - Positions the object uniformly at random entirely contained in the given Region - * - :sampref:`on ({region} | {Object} | {vector})` - - Positions the base of the object uniformly at random in the given Region, or modifies the position so that the base is in the Region. + * - :sampref:`on {vector}` + - Positions the base of the object at the given global coordinates + * - :sampref:`on ({region} | {Object})` + - Positions the object uniformly at random or modifies the position so that base of the Object is in the given Region/on the given Object. * - :sampref:`offset by {vector}` - Positions the object at the given coordinates in the local coordinate system of ego (which must already be defined) * - :sampref:`offset along {direction} by {vector}` diff --git a/src/scenic/core/type_support.py b/src/scenic/core/type_support.py index c84741eeb..f19fe681b 100644 --- a/src/scenic/core/type_support.py +++ b/src/scenic/core/type_support.py @@ -154,12 +154,12 @@ def canCoerceType(typeA, typeB): return issubclass(typeA, typeB) -def canCoerce(thing, ty): +def canCoerce(thing, ty, exact=False): """Can this value be coerced into the given type?""" tt = underlyingType(thing) if canCoerceType(tt, ty): return True - elif isinstance(thing, Distribution): + elif (not exact) and isinstance(thing, Distribution): return True # fall back on type-checking at runtime else: return False diff --git a/src/scenic/syntax/veneer.py b/src/scenic/syntax/veneer.py index 28557b4dd..ae1628a17 100644 --- a/src/scenic/syntax/veneer.py +++ b/src/scenic/syntax/veneer.py @@ -1425,15 +1425,15 @@ def On(thing): if isA(thing, Object): # Target is an Object: use its onSurface. target = thing.onSurface + elif canCoerce(thing, Vector, exact=True): + # Target is a vector + target = toVector(thing) elif canCoerce(thing, Region): # Target is a region (or could theoretically be coerced to one), # so we can use it as a target. - target = thing + target = toType(thing, Region) else: - # Target is a vector, so we can use it as a target. - target = toType( - thing, Vector, 'specifier "on R" with R not a Region, Object, or Vector' - ) + raise TypeError('specifier "on R" with R not a Region, Object, or Vector') props = {"position": 1}