# Difference between revisions of "Extrusion Edge Cases"

Line 9: | Line 9: | ||

The algorithm boils down to determining two vectors for every spine point - Y and Z. X is then calculated by cross product of those two. | The algorithm boils down to determining two vectors for every spine point - Y and Z. X is then calculated by cross product of those two. | ||

− | For Y, there are the following rules, in order of precedence as suggested by the standard: | + | For SCP Y, there are the following rules, in order of precedence as suggested by the standard: |

- subtracting the next spine point from the previous one, let's call it "the angle rule" (open spines are treated as cyclical) | - subtracting the next spine point from the previous one, let's call it "the angle rule" (open spines are treated as cyclical) | ||

Line 15: | Line 15: | ||

- subtracting the current spine point from the previous one, let's call those two together "the endpoint rules" (last point in an open spine) | - subtracting the current spine point from the previous one, let's call those two together "the endpoint rules" (last point in an open spine) | ||

- using the spine direction, in case of a fully collinear spine (the notion of "spine direction" is not defined) | - using the spine direction, in case of a fully collinear spine (the notion of "spine direction" is not defined) | ||

− | - reuse and look-ahead, suggested implicitly by the "coincident points have the same SCP" line in the spec | + | - reuse and look-ahead within the point cluster, suggested implicitly by the "coincident points have the same SCP" line in the spec |

− | For Y, collinear spine segments are not a problem. Null segments (AKA conincident points), however, are. | + | For SCP Y, collinear spine segments are not a problem. Null segments (AKA conincident points), however, are. |

− | For Z, there are the following rules, in the suggested order of preference: | + | For SCP Z, there are the following rules, in the suggested order of preference: |

- cross product of the two adjacent spine segments, let's call it "the angle rule" | - cross product of the two adjacent spine segments, let's call it "the angle rule" | ||

Line 26: | Line 26: | ||

- the Z axis of the coordinate system, rotated (the case of entirely collinear splines) | - the Z axis of the coordinate system, rotated (the case of entirely collinear splines) | ||

− | For Z calculation, both null and collinear spine segments warrant special treatment. | + | For SCP Z calculation, both null and collinear spine segments warrant special treatment. |

=== Coincident Spine Points === | === Coincident Spine Points === | ||

− | Conincident spine points are allowed under the spec. For those, the rules for generating Y are in conflict. | + | Conincident spine points are allowed under the spec. For those, the rules for generating Y are in conflict. The difference of the adjacent spine points might not be a null vector; the subtraction rule and the reuse/lookahead rule are in conflict here, and might provide different results (see the example below, for point #3). The standard doesn't specify which rule takes precedence. If the reuse rule is only supposed to kick in if the subtraction rule returns a null vector, the standard might as well say so. |

− | The spirit of the spec, however, might suggest that the applicability of the angle/endpoint rules for both Y and Z can be extended by replacing the notions of the next/previous point with next/previous '''distinct''' point.With this amendment, the reuse/look-ahead rule becomes unnecessary. | + | The spirit of the spec, however, might suggest that the applicability of the angle/endpoint rules for both Y and Z can be extended by replacing the notions of the next/previous point with next/previous '''distinct''' point.With this amendment, the reuse/look-ahead rule becomes unnecessary. The spec does mention the desire that the SCP Y approximate the tangent to the spine. |

− | + | However, introducing such a differece in rules might throw off existing implementations. Again, some existing implementations (e. g. X3DOM) are non-compliant with the current spec as it is. | |

− | The case of three coincident spine points. | + | ==== Example ==== |

+ | |||

+ | The case of three coincident spine points. We have a cluster of three coincident points in the middle. | ||

[[File:threecoin.jpg]] | [[File:threecoin.jpg]] | ||

− | For point #1, the angle rule | + | For point #1, the angle rule produces the vector {{overline|(01)}} (in red). |

− | For point #2, the angle rule produces a null Y. The reuse rule suggests the vector {{overline|(01)}} (in red). The extended angle rule, on the other hand, would produce Y as the vector {{overline|(04)}} (in green). | + | For point #2, the angle rule produces a null Y. The reuse rule suggests the vector {{overline|(01)}} (in red). The suggested extended angle rule, on the other hand, would produce Y as the vector {{overline|(04)}} (in green). |

For point #3, the angle rule would produce {{overline|(34)}} (in yellow), but the reuse rule would produce {{overline|(01)}} (red). This is a case of two rules producing valid but different results. That's why some kind of clarification of rule precedence in the spec would be necessary. The same unresolved contradiction in rules would arise even in case of two conincident points in the middle of a spine. | For point #3, the angle rule would produce {{overline|(34)}} (in yellow), but the reuse rule would produce {{overline|(01)}} (red). This is a case of two rules producing valid but different results. That's why some kind of clarification of rule precedence in the spec would be necessary. The same unresolved contradiction in rules would arise even in case of two conincident points in the middle of a spine. | ||

− | The | + | The extended angle rule would still produce {{overline|(04)}} (green) for point # 3. |

− | It's worth noting that for a spine like this, '''none''' of the existing rules would produce a nonnull SCP Z for any of the points. The extended angle rule, however would; the Z would be produced as {{overline|(10)}}×{{overline|(34)}} | + | It's worth noting that for a spine like this, '''none''' of the existing rules for Z would produce a nonnull SCP Z for any of the points. The extended angle rule, however, would; the Z would be produced as {{overline|(10)}}×{{overline|(34)}} |

A similar example can be drawn up for an open spine with two conincident spine points in the beginning or in the end. | A similar example can be drawn up for an open spine with two conincident spine points in the beginning or in the end. | ||

+ | |||

+ | The following geometry implements the example: | ||

+ | |||

+ | <code><Extrusion spine="-1 0 0 0 0 0 1 1 0 1 1 0 1 1 0 2 0 0" crossSection="-1 0 1 1 1 0" scale="1 1 1 1 1 1 2 2 3 3 3 3"/></code> | ||

+ | |||

+ | The first spine point at (-1,0,0) was added to give it a valid SCP Z. | ||

+ | |||

+ | X3DOM, Xj3D and InstantReality all produce extremely bizarre shapes for such a node. | ||

+ | |||

=== Collinear spines === | === Collinear spines === | ||

− | If the spine is collinear (and thus allows for no SCP | + | If the spine is entirely collinear (and thus allows for no SCP Z calculation by the angle rule), the standard calls for generating the SCP in the following manner ("the rotation rule"): |

+ | |||

+ | - The direction of the spine is determined (as a unit vector) | ||

+ | - The rotation that takes the vector {{Overline:(0,1,0)}} to the said direction vector is calculated | ||

+ | - This rotation is applied to vectors {{Overline|(1,0,0)}} and {{Overline|(0,0,1)}, and those are the X and Z axes of the SCP. | ||

+ | |||

+ | X3DDOM implements the rotation rule in a weird way. Under X3DOM, an extrusion in in X or Z direction looks completely flat. | ||

+ | |||

+ | Discounting that, there are some problems with the rule. | ||

+ | |||

+ | === Straight spine in -Y direction === | ||

+ | |||

+ | If the vector in the 1st step happens to be (0,-1,0), the rotation in the 2nd step is not unique. X3DOM, InstantReality, and Xj3D implement this case in three different ways. Consider the following scene: | ||

+ | |||

+ | <code> | ||

+ | <Shape> | ||

+ | <Appearance><Material diffuseColor="0 0.5 0.5"/></Appearance> | ||

+ | <Extrusion spine="0 0 0 0 1 0" solid="false" crossSection="-1 0 1 1 1 0 -1 0"/> | ||

+ | </Shape> | ||

+ | |||

+ | <Shape> | ||

+ | <Appearance><Material diffuseColor="0 0.5 0.5"/></Appearance> | ||

+ | <Extrusion spine="3 1 0 3 0 0" solid="false" crossSection="-1 0 1 1 1 0 -1 0"/> | ||

+ | </Shape> | ||

+ | </code> | ||

+ | |||

+ | It looks three different ways under X3DOM, Xj3D, and InstantReality. | ||

+ | |||

+ | |||

+ | === Spine with ambiguous direction === | ||

− | + | The spec doesn't specify what constitutes the "spine direction". It refers to to "the vector formed by the spine points", but depending on the choice of points, it might be a different vector (up to the sign), or even a null one. Common sense suggests the first nonzero length spine segment, but the standard doesn't say so. If the spine goes: (0,0,0) - (0,1,0) - (0,0,0), it's collinear, but what is its direction? | |

− | + | ||

− | + | ||

− | + | Consider the following geometry: | |

− | + | <code><Extrusion spine="0 0 0 0 1 0 0 0 0" solid="false" scale="1 1 1.2 1.2 1.4 1.4"/></code> | |

− | + | Under Xj3D and X3DOM is doesn't appear at all. Under InstantReality, it appears, but the inner fold isn't there. | |

− | |||

== Possible solutions == | == Possible solutions == |

## Revision as of 09:58, 29 October 2015

The Extrusion node specification has ambiguities [1]

This wiki page supports discussion on the x3d-public mailing list regarding Extrusion specification edge cases that make consistent modeling difficult.

## Contents

## Problem issues

The algorithm for generating the spine-aligned cross section plane (SCP) is ambiguous, hard to follow, sometimes ill-defined.

The algorithm boils down to determining two vectors for every spine point - Y and Z. X is then calculated by cross product of those two.

For SCP Y, there are the following rules, in order of precedence as suggested by the standard:

- subtracting the next spine point from the previous one, let's call it "the angle rule" (open spines are treated as cyclical) - subtracting the next spine point from the current one (first point in an open spine) - subtracting the current spine point from the previous one, let's call those two together "the endpoint rules" (last point in an open spine) - using the spine direction, in case of a fully collinear spine (the notion of "spine direction" is not defined) - reuse and look-ahead within the point cluster, suggested implicitly by the "coincident points have the same SCP" line in the spec

For SCP Y, collinear spine segments are not a problem. Null segments (AKA conincident points), however, are.

For SCP Z, there are the following rules, in the suggested order of preference:

- cross product of the two adjacent spine segments, let's call it "the angle rule" - reuse of the previous Z (if available) - look-ahead to the first defined Z (if not) - the Z axis of the coordinate system, rotated (the case of entirely collinear splines)

For SCP Z calculation, both null and collinear spine segments warrant special treatment.

### Coincident Spine Points

Conincident spine points are allowed under the spec. For those, the rules for generating Y are in conflict. The difference of the adjacent spine points might not be a null vector; the subtraction rule and the reuse/lookahead rule are in conflict here, and might provide different results (see the example below, for point #3). The standard doesn't specify which rule takes precedence. If the reuse rule is only supposed to kick in if the subtraction rule returns a null vector, the standard might as well say so.

The spirit of the spec, however, might suggest that the applicability of the angle/endpoint rules for both Y and Z can be extended by replacing the notions of the next/previous point with next/previous **distinct** point.With this amendment, the reuse/look-ahead rule becomes unnecessary. The spec does mention the desire that the SCP Y approximate the tangent to the spine.

However, introducing such a differece in rules might throw off existing implementations. Again, some existing implementations (e. g. X3DOM) are non-compliant with the current spec as it is.

#### Example

The case of three coincident spine points. We have a cluster of three coincident points in the middle.

For point #1, the angle rule produces the vector (01) (in red).

For point #2, the angle rule produces a null Y. The reuse rule suggests the vector (01) (in red). The suggested extended angle rule, on the other hand, would produce Y as the vector (04) (in green).

For point #3, the angle rule would produce (34) (in yellow), but the reuse rule would produce (01) (red). This is a case of two rules producing valid but different results. That's why some kind of clarification of rule precedence in the spec would be necessary. The same unresolved contradiction in rules would arise even in case of two conincident points in the middle of a spine.

The extended angle rule would still produce (04) (green) for point # 3.

It's worth noting that for a spine like this, **none** of the existing rules for Z would produce a nonnull SCP Z for any of the points. The extended angle rule, however, would; the Z would be produced as (10)×(34)

A similar example can be drawn up for an open spine with two conincident spine points in the beginning or in the end.

The following geometry implements the example:

`<Extrusion spine="-1 0 0 0 0 0 1 1 0 1 1 0 1 1 0 2 0 0" crossSection="-1 0 1 1 1 0" scale="1 1 1 1 1 1 2 2 3 3 3 3"/>`

The first spine point at (-1,0,0) was added to give it a valid SCP Z.

X3DOM, Xj3D and InstantReality all produce extremely bizarre shapes for such a node.

### Collinear spines

If the spine is entirely collinear (and thus allows for no SCP Z calculation by the angle rule), the standard calls for generating the SCP in the following manner ("the rotation rule"):

- The direction of the spine is determined (as a unit vector) - The rotation that takes the vector Template:Overline:(0,1,0) to the said direction vector is calculated - This rotation is applied to vectors (1,0,0) and {{Overline|(0,0,1)}, and those are the X and Z axes of the SCP.

X3DDOM implements the rotation rule in a weird way. Under X3DOM, an extrusion in in X or Z direction looks completely flat.

Discounting that, there are some problems with the rule.

### Straight spine in -Y direction

If the vector in the 1st step happens to be (0,-1,0), the rotation in the 2nd step is not unique. X3DOM, InstantReality, and Xj3D implement this case in three different ways. Consider the following scene:

```
<Shape>
```

```
``` <Appearance><Material diffuseColor="0 0.5 0.5"/></Appearance>
<Extrusion spine="0 0 0 0 1 0" solid="false" crossSection="-1 0 1 1 1 0 -1 0"/>

</Shape>

<Shape>

<Appearance><Material diffuseColor="0 0.5 0.5"/></Appearance>
<Extrusion spine="3 1 0 3 0 0" solid="false" crossSection="-1 0 1 1 1 0 -1 0"/>

```
</Shape>
```

It looks three different ways under X3DOM, Xj3D, and InstantReality.

### Spine with ambiguous direction

The spec doesn't specify what constitutes the "spine direction". It refers to to "the vector formed by the spine points", but depending on the choice of points, it might be a different vector (up to the sign), or even a null one. Common sense suggests the first nonzero length spine segment, but the standard doesn't say so. If the spine goes: (0,0,0) - (0,1,0) - (0,0,0), it's collinear, but what is its direction?

Consider the following geometry:

`<Extrusion spine="0 0 0 0 1 0 0 0 0" solid="false" scale="1 1 1.2 1.2 1.4 1.4"/>`

Under Xj3D and X3DOM is doesn't appear at all. Under InstantReality, it appears, but the inner fold isn't there.