diff --git a/.gitignore b/.gitignore index a4e7175e..786e5933 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ coverage npm-debug.log node_modules debug.log -types \ No newline at end of file +types diff --git a/.npmignore b/.npmignore index 6f9435ea..130f1344 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,4 @@ **/tsconfig.json **/webpack.config.js node_modules -src \ No newline at end of file +src diff --git a/README.md b/README.md index 67b7812e..78866d01 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ +README.md is a mess, need to start from manifesto's and re-do! + # manifesto [](https://github.com/IIIF-Commons/manifesto/actions/workflows/build-test.yml) -IIIF Presentation API client and server utility library. +Forked from [IIIF-Commons/manifesto](https://github.com/IIIF-Commons/manifesto). - npm install manifesto.js --save +Goal of implementing the [Draft API](https://github.com/IIIF/3d/blob/main/temp-draft-4.md) under development by the [IIIF 3D Technical Study Group](https://github.com/IIIF/3d/). > [!NOTE] > 3D extensions to the manifesto.js library are under development in a fork [IIIF-Commons/manifesto-3d](https://github.com/IIIF-Commons/manifesto-3d). @@ -15,21 +17,61 @@ IIIF Presentation API client and server utility library. ### Documentation -https://iiif-commons.github.io/manifesto/ +[Manifesto-3D.js](https://iiif-commons.github.io/manifesto-3d/) + +### Loading through package manager + + npm install manifesto-3d.js --save + +### Demonstration Projects +[Example manifests](https://github.com/IIIF/3d/tree/main/manifests) conforming to the [Draft API](https://github.com/IIIF/3d/blob/main/temp-draft-4.md) . + +[Prototype Viewers](https://github.com/IIIF/3d/issues/28) rendering the example manifests. +- [Three-JS based viewer](https://codesandbox.io/p/github/JulieWinchester/iiif-threejs-demo) +- [X3D/X3DOM based viewer](https://codesandbox.io/p/github/vincentmarchetti/iiif-x3dom-demo/main) +- [Smithsonian Voyager](https://codesandbox.io/p/sandbox/voyager-annotations-demo-forked-l83l6w) + +### ChangeLog + +From start point of the version distributed from [JulieWinchester/manifesto](https://github.com/JulieWinchester/manifesto/tree/3dtsg-dev-dist) + +#### To package.json version 4.3.0-draft3dapi.0.1.0 +distributed from [vincentmarchetti/manifesto#3dtsg-main]() there were these changes: + +1. This test is no longer useful for the Target of an Annotation: + + if ( typeof(target) === "string" ){ + // handle case where target is a Scene + } + + Draft manifest [ 3_lights/direction_light_transform ]( https://github.com/IIIF/3d/blob/main/manifests/3_lights/direction_light_transform_rotate.json ) uses two ways of encoding the value of a target property for an Annotation: with a json string value of the IRI, or with an object with `id` property of the IRI for the Scene. To avoid exponential expansion of if-else code when combined with target property which can also be `SpecificResource` resources, the parsing code was changed so tha the value returned from `getTarget()` is always an object. + + Since the Target property will always be an object referencing a `Scene`, or a `SpecificResource` whose `source` property is a `Scene`, the code for handling either would be + + if (target.isSpecificResource){ + // handle a SpecificResource, with selector property + // and whose source property is the Scene + } + else{ + // handle a Scene directly + } + +2. Annotation.getBody3D() is deprecated. + + The `Annotation.getBody()` from the Presentation 3 code has been extended to support the resources that can be included in a 3d Annotation body property. An important difference is that the `getBody()` function returns an array of objects, while the `getBody3D()` returns a single object. The deprecated function `getBody3D()` should be replaced with `getBody()[0]` + +#### To package.json version 4.3.0-draft3dapi.0.2.0 + +1. Fixed a bug that occurred in determining the 'source' property of a SpecificResource resource that is the "target" property of an Annotation. This bug escaped detection previously because in the 3D case this 'source' property has always been a Scene resource, and the value is not needed for visualization. + +#### To package.json version 4.3.0-draft3dapi.0.3.0 + +1. Added isSpecificResource and isAnnotationBody properties to the SpecificResource and AnnotationBody classes, in response to developer suggestion. (Slack, Apr 24 2024) -### Developer Setup +#### To package.json version 4.3.0-draft3dapi.0.4.0 - git clone https://github.com/iiif-commons/manifesto.git - npm install - npm build - npm test +1. Implemented Perspective Camera properties in the Camera class. -### Publishing Package +#### To package.json version 4.3.0-draft3dapi.0.5.0 - git checkout main - npm version patch - npm run docs - git add . - git commit -m "Release v1.2.3" - git tag v1.2.3 - git push origin main v1.2.3 +1. Implement lookAt property of Camera class and of Light class. diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..a29188c9 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,9 @@ +# Release + +To create a new release on NPM you need to create a [release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) on Github and the [release.yml](.github/workflows/release.yml) action will then deploy a release on NPM. + +This requires NPM_TOKEN to be setup as a repository secret. This will update the package at: + +https://www.npmjs.com/package/@iiif/3d-manifesto-dev + +To update the version number in NPM you will also need to update the version number in [package.json](package.json). \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index eaa8dacc..0b09ad48 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -1,16 +1,20 @@ :root { - --light-hl-0: #000000; - --dark-hl-0: #D4D4D4; - --light-hl-1: #098658; - --dark-hl-1: #B5CEA8; - --light-hl-2: #795E26; - --dark-hl-2: #DCDCAA; - --light-hl-3: #001080; - --dark-hl-3: #9CDCFE; - --light-hl-4: #0000FF; - --dark-hl-4: #569CD6; - --light-hl-5: #A31515; - --dark-hl-5: #CE9178; + --light-hl-0: #0000FF; + --dark-hl-0: #569CD6; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #001080; + --dark-hl-2: #9CDCFE; + --light-hl-3: #795E26; + --dark-hl-3: #DCDCAA; + --light-hl-4: #008000; + --dark-hl-4: #6A9955; + --light-hl-5: #098658; + --dark-hl-5: #B5CEA8; + --light-hl-6: #267F99; + --dark-hl-6: #4EC9B0; + --light-hl-7: #A31515; + --dark-hl-7: #CE9178; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -22,6 +26,8 @@ --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); --code-background: var(--light-code-background); } } @@ -32,6 +38,8 @@ --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); --code-background: var(--dark-code-background); } } @@ -42,6 +50,8 @@ --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); --code-background: var(--light-code-background); } @@ -52,6 +62,8 @@ --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); --code-background: var(--dark-code-background); } @@ -61,4 +73,6 @@ .hl-3 { color: var(--hl-3); } .hl-4 { color: var(--hl-4); } .hl-5 { color: var(--hl-5); } +.hl-6 { color: var(--hl-6); } +.hl-7 { color: var(--hl-7); } pre, code { background: var(--code-background); } diff --git a/docs/classes/AnnotationBodyParser.html b/docs/classes/AnnotationBodyParser.html new file mode 100644 index 00000000..fd67daa2 --- /dev/null +++ b/docs/classes/AnnotationBodyParser.html @@ -0,0 +1,3 @@ +
StaticBuildOptionaloptions: IManifestoOptionsOptionaljsonld: anyOptionaloptions: IManifestoOptionsFar plane value of the camera. +*
+Full angular size of perspective viewport in vertical direction. +Angular unit is degrees +*
+Near plane value of the camera. +*
+the far plane value, i.e. the maximum distance from the camera at +which something in the space must exist in order to be viewed by the camera. +*
+full angular size of perspective viewport in vertical direction. +Angular unit is degrees +*
+returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property
+: if not null, is either a PointSelector, an object +with an id matching the id of an Annotation instance, or a +SpecificResource with a PointSelector .
+the near plane value, i.e. the minimum distance from the camera at +which something in the space must exist in order to be viewed by the camera. +*
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+full linear size of orthographic viewport in vertical direction. +linear unit is Scene global unit of measure
+Name of this property was originally Height, has been changed +at this revision to ViewHeight: +See issues at https://github.com/IIIF/api/issues/2289 +*
+class structure with red, green, blue values in 0-255 range +Uses the color-string +library for conversion from and to string representations of color.
+Array of three 0-255 integers for r,g,b value. Ex: [255.0,0] for red
+0 to 255 value of blue color component
+hex string (as for CSS ) representation of r,g,b components
+0 to 255 value of green color component
+0 to 255 value of red color component
+OptionalcompareFn: ((a: Language, b: Language) => number)Function used to determine the order of the elements. It is expected to return a negative value if the first argument is less than the second argument, zero if they're equal, and a positive -value otherwise. If omitted, the elements are sorted in ascending, ASCII character order.
-[11,2,22,1].sort((a, b) => a - b)
+value otherwise. If omitted, the elements are sorted in ascending, UTF-16 code unit order.
+[11,2,22,1].sort((a, b) => a - b)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
diff --git a/docs/classes/Light.html b/docs/classes/Light.html new file mode 100644 index 00000000..c422a22a --- /dev/null +++ b/docs/classes/Light.html @@ -0,0 +1,98 @@ +With the 3D extensions to the IIIF Presentation API the name of this +class is misleading, but for now is being retained for the sake backward +compatibility with earlier manifesto code and tests.
+The 3D extensions allow that the body property of an annotation can be +a light, camera, or model, or a SpecificResource object wrapping a light, camera, +or model. +*
+Optionaljsonld: anyOptionaloptions: IManifestoOptionsAs defined in the temp-draft-4.md ( +https://github.com/IIIF/3d/blob/main/temp-draft-4.md#lights ; 12 May 2024) +this quantity is the half-angle of the cone of the spotlight.
+The inconsistency between this definition of the angle and the definition of +fieldOfView for PerspectiveCamera (where the property value defines the full angle) has +already been noted: https://github.com/IIIF/api/issues/2284
+provisional decision is to return undefined in case that this property +is accessed in a light that is not a spotlight
+number
+The implementation of the intensity is based on +temp-draft-4.md +and the example 3D manifests +lights +on 24 Mar 2024. The intensity property in the manifest is an object +with declared type 'Value', a numeric property named 'value' and a +property named unit . This implementation will only work with a unit == 'relative' +and it will be assumed that a relative unit value of 1.0 corresponds to the +brightest light source a rendering engine supports.
+This code will implement a default intensity of 1.0
+returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property
+: if not null, is either a PointSelector, or an object +with an id matching the id of an Annotation instance.
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+the 3D coordinates of the point as a Vector3 instance. +*
+the 3D coordinates of the point as a Vector3 instance. +*
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+OptionalcompareFn: ((a: LocalizedValue, b: LocalizedValue) => number)Function used to determine the order of the elements. It is expected to return a negative value if the first argument is less than the second argument, zero if they're equal, and a positive -value otherwise. If omitted, the elements are sorted in ascending, ASCII character order.
-[11,2,22,1].sort((a, b) => a - b)
+value otherwise. If omitted, the elements are sorted in ascending, UTF-16 code unit order.
+[11,2,22,1].sort((a, b) => a - b)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
diff --git a/docs/classes/RotateTransform.html b/docs/classes/RotateTransform.html new file mode 100644 index 00000000..ab72f7c6 --- /dev/null +++ b/docs/classes/RotateTransform.html @@ -0,0 +1,31 @@ +Optionaljsonld: anyaccessor Rotation is an object with x,y,z attributes whose values are +a counter-clockwise rotation in degrees about the fixed coordinate +system axes.
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+Returns an object with x,y,z attributes whose values are +a counter-clockwise rotation in degrees about the fixed coordinate +system axes.
+object
+Optionaljsonld: anyA function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+Developer note: This implementation does not strictly adhere +to the description of SpecificResource in the Web Annotation Model +document https://www.w3.org/TR/annotation-model/ +section 4 : https://www.w3.org/TR/annotation-model/#specific-resources
+The getTransform() method returning an Array of 3D Transfom resources, is +an extension of SpecificResource beyond the web annotation model.
+Optionaloptions: IManifestoOptionsreturns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+An implementation of the TextualBody class (class in JSON-LD sense) +as it is described in Web Annotation Data Model Section 3.2.4 +https://www.w3.org/TR/annotation-model/#embedded-textual-body +*
+Optionaljsonld: anyOptionaloptions: IManifestoOptionsThe simple string that is the data content of this resource +will return empty string as a default value +*
+returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property
+Returns a specific resource representing the TextualBody position if +present, otherwise null. +*
+A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+AbstractOptionaljsonld: anyA function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+Optionaljsonld: anyA function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier
+If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.
+performs the calculation required for the lookAt +property of a camera resource. Determines the +required angles of two rotations, the first about +the x axis and the second about the y axis, which will +rotate the default camera direction (0,0,-1) into the +direction of the input arguments
+Result of calculation is returned as a instance of EulerAngle from the +threejs-math library. The "axes order" of the EulerAngle is "YXZ": The +three-js library uses body-fixed axes to represent EulerAngles, which reverse +the ordering of the "relative rotation" algorithm described in the +draft 3d api.
+A vector interpreted as a direction. Client code +responsible for not passing a 0-length vector, else a
+threejs-math.EulerAngle instance
+Given an array of Transform instances, returns a single Matrix4 +instance that represents the cumulative effect of the transforms +in the order they appear in the array.
+An array of Transform instances
+A Matrix4 instance representing the cumulative effect of the transforms
+Implements the convention that the 3 component values for the RotateTranform +cass (properties x,y,z) are to be interpreted as Euler angles in the intrinsic XYZ +order
+: A object with a Rotation member object, properties x,y,z
+threejs-math.EulerAngle instance. From this threejs-math functionsa +allow conversion to other rotation representations.
+Evaluates the rotation required to transform a directional light +or spot ling, which in iiif 3D spec +have an initial direction in the -Y direction, to a direction +along the input argument
+TODO : expand on this documentation taking into account the +implied specification that RotateTransform instances +are to be interpreted as an Euler angle definition of +the rotation
+A vector interpreted as a direction. Client code +responsible for not passing a 0-length vector, else a
+threejs-math.EulerAngle instance
+
With the 3D extensions to the IIIF Presentation API the name of this +class is misleading, but for now is being retained for the sake backward +compatibility with earlier manifesto code and tests.
+The 3D extensions allow that the body property of an annotation can be +a light, camera, or model, or a SpecificResource object wrapping a light, camera, +or model. +*
+