Publish using Cropping Option
VidiEditor supports cropping of the timeline output while simply adding a cropping mask to the timeline player (see also Mobile Aspect Ratio When Publishing Output).
![image-20240327-191400.png](../../__attachments/3481666358/image-20240327-191400.png?inst-v=8eb1641d-0ec8-4453-b073-5adc28ea6e41)
Example User Selection for Cropping
The cropped area in pixels to left and right must be calculated on Publish and depends on the target shape tags resolution (width). This action can be performed in by VidiEditor under 2 assumptions:
The user selects the target shape tag in the Publish GUI
The target shape tag contains the resolution parameter
<video>
<scaling>
<width>1920</width>
<height>1080</height>
</scaling>
</video>
This is often the case anyway it is possible to configure VidiEditor in a way where this is not given. For example:
The target dimensions should be evaluated from the source and the parameter is not part of the shape tag
The Publish dialogue is configured in a way where the user only selects a VidiFlow Workflow but no Shape Tag - the Shape Tag is defined by the Workflow
A Workflow overwrite the chosen Shape Tag for some reason
In such a scenario VidiEditor would not be able to calculate the cropping area in pixels as the target dimensions are unknown. Please also compare to VidiFlow Workflows for Publish where the general Publish Workflow is explained.
To overcome this, the needed calculation can be applied in the workflow as follows:
TargetAspectRatio Input Parameter
The Workflow must be set up with an input parameter named “TargetAspectRatio“. VidiEditor will assign user selected aspect ratio from VE timeline player into this variable to make it available to the workflow.
This parameter is essential for the workflow when target shape tag is set within the workflow, so that workflow able to calculate the new video scaling with additional steps.
Simplified Workflow Setup Example
An easy publish Workflow for this can look as follows:
![image-20240327-192854.png](../../__attachments/3481666358/image-20240327-192854.png?inst-v=8eb1641d-0ec8-4453-b073-5adc28ea6e41)
3. Read out the Publish Items Sequence
The needed cropping must be applied to the Sequence Document descibing the VidiEditor EDL. So in a first step this must be read out via “Get Sequence Item Document” with a suitable ItemID (The Item created on Publish) in following syntax: pf://platform/item/ITEM-VX-4690/
The Item Id can be also fetched from the Workflow Input parameters “SourceItemUri“.
Get the ShapeTag or set the wanted target resolution
Also the target width of the video to be rendered is needed. This can be set explicitly but probably its more realistic it will be fetched from a ShapeTag set inside the Workflow using “Get ShapeTag” if not already existing in the Workflow.
Calculate the cropping in a Script Task
Execute a script task to calculate the new video scaling based on the aspect ratio and shapetag, producing the output named "ModifiedSequenceDocument" in this example. The script itself could look as follows:
var sequenceDoc = "";
sequenceDoc = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.toString(execution.getVariable("SequenceDocument"));
var shapetag = "";
shapetag = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.toString(execution.getVariable("ShapeTag"));
shapetag = JSON.parse(shapetag);
var targetAspectRatio = "";
targetAspectRatio = execution.getVariable("TargetAspectRatio");
var overrideContent = '';
if (shapetag) {
overrideContent = getVideoScalingOverrideValue(targetAspectRatio, shapetag.video?.scaling?.width, shapetag.video?.scaling?.height);
// Define a regular expression to match <override> tag in the XML string
const overrideRegex = /<override>([\s\S]*?)<\/override>/;
// Match the <override> tag in the XML string
const overrideMatch = overrideRegex.exec(sequenceDoc) || false;
if (overrideMatch) {
// If <override> tag exists, append or replace <video> content
const existingOverrideContent = overrideMatch[1].trim();
const videoTagRegex = /<video>([\s\S]*?)<\/video>/;
if (videoTagRegex.test(existingOverrideContent)) {
// If <video> tag exists, then check <scaling> tag
const videoContent = videoTagRegex.exec(existingOverrideContent)[1];
const scalingTagRegex = /<scaling>([\s\S]*?)<\/scaling>/;
if (scalingTagRegex.test(videoContent)) {
// If <scaling> tag exists within <video> tag, replace content
const updatedVideoContent = videoContent.replace(scalingTagRegex, overrideContent);
const updatedOverrideContent = existingOverrideContent.replace(videoContent, updatedVideoContent);
sequenceDoc = sequenceDoc.replace(overrideRegex, `<override>${updatedOverrideContent}</override>`);
} else {
// If <scaling> tag doesn't exist within <video> tag, append it
const updatedOverrideContent = existingOverrideContent.replace('</video>', `${overrideContent}</video>`);
sequenceDoc = sequenceDoc.replace(overrideRegex, `<override>${updatedOverrideContent}</override>`);
}
} else {
// If empty <video/> tag exists
const emptyVideoTagRegex = /<video\/>/;
if (emptyVideoTagRegex.test(existingOverrideContent)) {
sequenceDoc = sequenceDoc.replace(`<video/>`, `<video>${overrideContent}</video>`);
} else {
// If <video> tag doesn't exist, append it
sequenceDoc = sequenceDoc.replace(existingOverrideContent, `${existingOverrideContent}<video>${overrideContent}</video>`);
}
}
} else {
// If <override> tag does not exist, append it with <video> content
sequenceDoc = sequenceDoc.replace('</SequenceDocument>', `<override><video>${overrideContent}</video></override></SequenceDocument>`);
}
var overrideContentData = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.createVpmsLongString(overrideContent);
execution.setVariable("OverrideScaling", overrideContentData);
var sequenceDocData = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.createVpmsLongString(sequenceDoc);
execution.setVariable("ModifiedSequenceDocument", sequenceDocData);
}
function getVideoScalingOverrideValue(aspectRatio, presetVideoWidth, presetVideoHeight) {
if (aspectRatio && aspectRatio !== "Standard") {
const valueSplit = aspectRatio.split(':');
if (valueSplit.length === 2) {
const horizontal = parseInt(valueSplit[0]) || 0;
const vertical = parseInt(valueSplit[1]) || 0;
const width = presetVideoWidth || 0;
const height = presetVideoHeight || 0;
if (horizontal > 0 && vertical > 0 && width > 0 && height > 0) {
const originalAspectRatio = "16:9";
const overrideCalculationValue = getAspectRatioCalculationValue(aspectRatio);
const originalCalculationValue = getAspectRatioCalculationValue(originalAspectRatio);
const calculationValue = originalCalculationValue / overrideCalculationValue;
const changeWidth = overrideCalculationValue > originalCalculationValue;
const difference = Math.floor(changeWidth ? ((width - (width * calculationValue)) / 2) : ((height - (height / calculationValue)) / 2));
if (difference > 0) {
return `<scaling>
<width>${width}</width>
<height>${height}</height>
<top>${changeWidth ? 0 : difference}</top>
<bottom>${changeWidth ? 0 : difference}</bottom>
<left>${changeWidth ? difference : 0}</left>
<right>${changeWidth ? difference : 0}</right>
</scaling>
`
} else {
return '';
}
}
return '';
}
return '';
} else {
return '';
}
}
function getAspectRatioCalculationValue(ratio) {
let calculationValue;
switch (ratio) {
case '16:9':
calculationValue = 9 / 16;
break;
case '16:10':
calculationValue = 10 / 16;
break;
case '4:3':
calculationValue = 3 / 4;
break;
case '4:5':
calculationValue = 5 / 4;
break;
case '9:16':
calculationValue = 16 / 9;
break;
case '1:1':
calculationValue = 1; // (1 / 1) = 1
break;
}
return calculationValue;
}
Execute a script task to generate the URI path for the final step
Perform a HTTP POST request to update the sequence document of the target item id with the content of the "ModifiedSequenceDocument.
Start the Conform Job using “RenderItemSequence” task
A complete sample BPMN extracted from the VidiFlow Workflow Designer can be found below:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:vpms="http://s4m.arvato-systems.de/schema/bpmn/vpmns" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" typeLanguage="http://schemas.microsoft.com/winfx/2006/xaml" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:itemDefinition id="ItemDefinition_String" itemKind="Physical" structureRef="String" />
<bpmn2:process id="ZLScriptTest1" name="ZLScriptTest1" isExecutable="true">
<bpmn2:extensionElements>
<vpms:contractParameters ObjectId="" ErrorMessage="">
<vpms:inputParameter name="SourceItemUri" type="string" direction="Input" optional="false" defaultValue="" typeInformation="{"Key":"PlatformUri","Value":null}" description="Platform Uri of the source item" examples="["pf://mysystemname/item/ITEM-VX-1/"]" />
<vpms:inputParameter name="TargetAspectRatio" type="string" direction="Input" optional="false" defaultValue="" description="" examples="[]" />
<vpms:inputParameter name="UriPath" type="string" direction="Input" optional="false" defaultValue="" typeInformation="{"Key":null,"Value":null}" description="Uri path for making the api call." examples="["item/VX-1","collection/VX-1/metadata","item"]" />
<vpms:outputParameter name="itemUrlForSequence" type="string" direction="Output" optional="false" defaultValue="" description="" examples="[]" />
<vpms:outputParameter name="ModifiedSequenceDocument" type="string" direction="Output" optional="false" defaultValue="" description="" examples="[]" />
<vpms:outputParameter name="OverrideScaling" type="string" direction="Output" optional="false" defaultValue="" description="" examples="[]" />
<vpms:outputParameter name="SequenceDocument" type="string" direction="Output" optional="false" defaultValue="" typeInformation="{"Key":null,"Value":null}" description="Sequence Document in XML format" examples="[]" />
<vpms:outputParameter name="ShapeTag" type="string" direction="Output" optional="false" defaultValue="" description="The response of the API as a string." examples="["{\"Response\":\"value\"}"]" />
</vpms:contractParameters>
</bpmn2:extensionElements>
<bpmn2:startEvent id="StartEvent_1">
<bpmn2:outgoing>Flow_0qb2e5o</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:sequenceFlow id="Flow_0qb2e5o" sourceRef="StartEvent_1" targetRef="Activity_02dqkje" />
<bpmn2:serviceTask id="Activity_02dqkje" name="Get Sequence Item Document" camunda:type="external" camunda:topic="Agent_GetSequenceDocument.d5704822-b00c-4457-8a44-5fd1125bcc1b_1.0" vpms:serviceTaskName="GetSequenceDocument" vpms:serviceTaskVersion="1.0">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="_AgentId_" vpms:type="string">Agent_GetSequenceDocument.d5704822-b00c-4457-8a44-5fd1125bcc1b_1.0</camunda:inputParameter>
<camunda:inputParameter name="SourceItemUri" vpms:type="string" vpms:isMandatory="true" vpms:typeInformation="{"Key":"PlatformUri","Value":null}">#{SourceItemUri}</camunda:inputParameter>
<camunda:outputParameter name="SequenceDocument" vpms:type="string" vpms:isInternal="false" vpms:typeInformation="{"Key":null,"Value":null}">#{SequenceDocument}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_0qb2e5o</bpmn2:incoming>
<bpmn2:outgoing>Flow_0j8icg1</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:sequenceFlow id="Flow_0j8icg1" sourceRef="Activity_02dqkje" targetRef="Activity_1mg16ke" />
<bpmn2:serviceTask id="Activity_1mg16ke" name="Get shapetag" camunda:type="external" camunda:topic="Agent_GetApiCall.9932e637-7efc-440f-ac44-e0b6a95cdbd8_3.0" vpms:serviceTaskName="GetApiCall" vpms:serviceTaskVersion="3.0">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="_AgentId_" vpms:type="string">Agent_GetApiCall.9932e637-7efc-440f-ac44-e0b6a95cdbd8_3.0</camunda:inputParameter>
<camunda:inputParameter name="Endpoint" vpms:type="string" vpms:isMandatory="true" vpms:typeInformation="{"Key":"RestEndpoint","Value":null}">${"11457fd4-0a36-4daa-91c5-2e91ebe81c21"}</camunda:inputParameter>
<camunda:inputParameter name="UriPath" vpms:type="string" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">#{UriPath}</camunda:inputParameter>
<camunda:inputParameter name="QueryString" vpms:type="string" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${""}</camunda:inputParameter>
<camunda:inputParameter name="HttpHeaderValues" vpms:type="json" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${S("{\"Accept\":\"application/json\",\"Content-Type\":\"application/xml\"}")}</camunda:inputParameter>
<camunda:outputParameter name="ShapeTag" vpms:type="string" vpms:isInternal="false">#{Response}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_0j8icg1</bpmn2:incoming>
<bpmn2:outgoing>Flow_1p8yuni</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:scriptTask id="Activity_08qi1oa" name="Calculate Scaling information" camunda:asyncBefore="true" camunda:asyncAfter="true" scriptFormat="JavaScript">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="TargetAspectRatio" vpms:type="string">#{TargetAspectRatio}</camunda:inputParameter>
<camunda:outputParameter name="ModifiedSequenceDocument" vpms:type="string">#{ModifiedSequenceDocument}</camunda:outputParameter>
<camunda:outputParameter name="OverrideScaling" vpms:type="string">#{OverrideScaling}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_1p8yuni</bpmn2:incoming>
<bpmn2:outgoing>Flow_05evvps</bpmn2:outgoing>
<bpmn2:script>var sequenceDoc = "";
sequenceDoc = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.toString(execution.getVariable("SequenceDocument"));
var shapetag = "";
shapetag = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.toString(execution.getVariable("ShapeTag"));
shapetag = JSON.parse(shapetag);
var targetAspectRatio = "";
targetAspectRatio = execution.getVariable("TargetAspectRatio");
var overrideContent = '';
if (shapetag) {
overrideContent = getVideoScalingOverrideValue(targetAspectRatio, shapetag.video?.scaling?.width, shapetag.video?.scaling?.height);
// Define a regular expression to match <override> tag in the XML string
const overrideRegex = /<override>([\s\S]*?)<\/override>/;
// Match the <override> tag in the XML string
const overrideMatch = overrideRegex.exec(sequenceDoc) || false;
if (overrideMatch) {
// If <override> tag exists, append or replace <video> content
const existingOverrideContent = overrideMatch[1].trim();
const videoTagRegex = /<video>([\s\S]*?)<\/video>/;
if (videoTagRegex.test(existingOverrideContent)) {
// If <video> tag exists, then check <scaling> tag
const videoContent = videoTagRegex.exec(existingOverrideContent)[1];
const scalingTagRegex = /<scaling>([\s\S]*?)<\/scaling>/;
if (scalingTagRegex.test(videoContent)) {
// If <scaling> tag exists within <video> tag, replace content
const updatedVideoContent = videoContent.replace(scalingTagRegex, overrideContent);
const updatedOverrideContent = existingOverrideContent.replace(videoContent, updatedVideoContent);
sequenceDoc = sequenceDoc.replace(overrideRegex, `<override>${updatedOverrideContent}</override>`);
} else {
// If <scaling> tag doesn't exist within <video> tag, append it
const updatedOverrideContent = existingOverrideContent.replace('</video>', `${overrideContent}</video>`);
sequenceDoc = sequenceDoc.replace(overrideRegex, `<override>${updatedOverrideContent}</override>`);
}
} else {
// If empty <video/> tag exists
const emptyVideoTagRegex = /<video\/>/;
if (emptyVideoTagRegex.test(existingOverrideContent)) {
sequenceDoc = sequenceDoc.replace(`<video/>`, `<video>${overrideContent}</video>`);
} else {
// If <video> tag doesn't exist, append it
sequenceDoc = sequenceDoc.replace(existingOverrideContent, `${existingOverrideContent}<video>${overrideContent}</video>`);
}
}
} else {
// If <override> tag does not exist, append it with <video> content
sequenceDoc = sequenceDoc.replace('</SequenceDocument>', `<override><video>${overrideContent}</video></override></SequenceDocument>`);
}
var overrideContentData = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.createVpmsLongString(overrideContent);
execution.setVariable("OverrideScaling", overrideContentData);
var sequenceDocData = com.s4m.dmm.platform.utility.VpmsStringVariableUtil.createVpmsLongString(sequenceDoc);
execution.setVariable("ModifiedSequenceDocument", sequenceDocData);
}
function getVideoScalingOverrideValue(aspectRatio, presetVideoWidth, presetVideoHeight) {
if (aspectRatio && aspectRatio !== "Standard") {
const valueSplit = aspectRatio.split(':');
if (valueSplit.length === 2) {
const horizontal = parseInt(valueSplit[0]) || 0;
const vertical = parseInt(valueSplit[1]) || 0;
const width = presetVideoWidth || 0;
const height = presetVideoHeight || 0;
if (horizontal > 0 && vertical > 0 && width > 0 && height > 0) {
const originalAspectRatio = "16:9";
const overrideCalculationValue = getAspectRatioCalculationValue(aspectRatio);
const originalCalculationValue = getAspectRatioCalculationValue(originalAspectRatio);
const calculationValue = originalCalculationValue / overrideCalculationValue;
const changeWidth = overrideCalculationValue > originalCalculationValue;
const difference = Math.floor(changeWidth ? ((width - (width * calculationValue)) / 2) : ((height - (height / calculationValue)) / 2));
if (difference > 0) {
return `<scaling>
<width>${width}</width>
<height>${height}</height>
<top>${changeWidth ? 0 : difference}</top>
<bottom>${changeWidth ? 0 : difference}</bottom>
<left>${changeWidth ? difference : 0}</left>
<right>${changeWidth ? difference : 0}</right>
</scaling>
`
} else {
return '';
}
}
return '';
}
return '';
} else {
return '';
}
}
function getAspectRatioCalculationValue(ratio) {
let calculationValue;
switch (ratio) {
case '16:9':
calculationValue = 9 / 16;
break;
case '16:10':
calculationValue = 10 / 16;
break;
case '4:3':
calculationValue = 3 / 4;
break;
case '4:5':
calculationValue = 5 / 4;
break;
case '9:16':
calculationValue = 16 / 9;
break;
case '1:1':
calculationValue = 1; // (1 / 1) = 1
break;
}
return calculationValue;
}
</bpmn2:script>
</bpmn2:scriptTask>
<bpmn2:sequenceFlow id="Flow_1p8yuni" sourceRef="Activity_1mg16ke" targetRef="Activity_08qi1oa" />
<bpmn2:serviceTask id="Activity_1231p3i" name="Update Sequence Document" camunda:type="external" camunda:topic="Agent_PutApiCall.fd44d022-845f-4d10-841f-7500932aa18a_2.0" vpms:serviceTaskName="PutApiCall" vpms:serviceTaskVersion="2.0">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="_AgentId_" vpms:type="string">Agent_PutApiCall.fd44d022-845f-4d10-841f-7500932aa18a_2.0</camunda:inputParameter>
<camunda:inputParameter name="Endpoint" vpms:type="string" vpms:isMandatory="true" vpms:typeInformation="{"Key":"RestEndpoint","Value":null}">${"11457fd4-0a36-4daa-91c5-2e91ebe81c21"}</camunda:inputParameter>
<camunda:inputParameter name="UriPath" vpms:type="string" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${itemUrlForSequence}</camunda:inputParameter>
<camunda:inputParameter name="QueryString" vpms:type="string" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${""}</camunda:inputParameter>
<camunda:inputParameter name="Payload" vpms:type="string" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${ModifiedSequenceDocument}</camunda:inputParameter>
<camunda:inputParameter name="HttpHeaderValues" vpms:type="json" vpms:isMandatory="false" vpms:typeInformation="{"Key":null,"Value":null}">${S("{\"Content-Type\":\"application/xml\"}")}</camunda:inputParameter>
<camunda:outputParameter name="Response_1qs2ls1" vpms:type="string" vpms:isInternal="true" vpms:typeInformation="{"Key":null,"Value":null}">#{Response}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_0ltipwb</bpmn2:incoming>
<bpmn2:outgoing>Flow_044r52u</bpmn2:outgoing>
</bpmn2:serviceTask>
<bpmn2:scriptTask id="Activity_0ur1yva" name="Update variable value for next step" camunda:asyncBefore="true" camunda:asyncAfter="true" scriptFormat="JavaScript">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:outputParameter name="itemUrlForSequence" vpms:type="string">#{itemUrlForSequence}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn2:extensionElements>
<bpmn2:incoming>Flow_05evvps</bpmn2:incoming>
<bpmn2:outgoing>Flow_0ltipwb</bpmn2:outgoing>
<bpmn2:script>var itemUrl = execution.getVariable("SourceItemUri")
var itemId = extractLastPart(itemUrl)
itemSequenceUrlPath = `item/${itemId}/sequence/vidispine`
execution.setVariable("itemUrlForSequence", itemSequenceUrlPath);
function extractLastPart(url) {
// Split the URL by '/'
const parts = url.split('/');
// Get the last part of the array
const lastPart = parts[parts.length - 2];
return lastPart;
}</bpmn2:script>
</bpmn2:scriptTask>
<bpmn2:sequenceFlow id="Flow_05evvps" sourceRef="Activity_08qi1oa" targetRef="Activity_0ur1yva" />
<bpmn2:sequenceFlow id="Flow_0ltipwb" sourceRef="Activity_0ur1yva" targetRef="Activity_1231p3i" />
<bpmn2:endEvent id="Event_12q67pq">
<bpmn2:incoming>Flow_044r52u</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="Flow_044r52u" sourceRef="Activity_1231p3i" targetRef="Event_12q67pq" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="ZLScriptTest1">
<bpmndi:BPMNEdge id="Flow_044r52u_di" bpmnElement="Flow_044r52u">
<di:waypoint x="930" y="220" />
<di:waypoint x="1032" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ltipwb_di" bpmnElement="Flow_0ltipwb">
<di:waypoint x="730" y="220" />
<di:waypoint x="830" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_05evvps_di" bpmnElement="Flow_05evvps">
<di:waypoint x="490" y="220" />
<di:waypoint x="630" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1p8yuni_di" bpmnElement="Flow_1p8yuni">
<di:waypoint x="280" y="220" />
<di:waypoint x="390" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0j8icg1_di" bpmnElement="Flow_0j8icg1">
<di:waypoint x="40" y="220" />
<di:waypoint x="180" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qb2e5o_di" bpmnElement="Flow_0qb2e5o">
<di:waypoint x="-142" y="220" />
<di:waypoint x="-60" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="-178" y="202" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_11xymgr_di" bpmnElement="Activity_02dqkje">
<dc:Bounds x="-60" y="180" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0pnpssg_di" bpmnElement="Activity_1mg16ke">
<dc:Bounds x="180" y="180" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0cygy7h_di" bpmnElement="Activity_08qi1oa">
<dc:Bounds x="390" y="180" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0i7asid_di" bpmnElement="Activity_1231p3i">
<dc:Bounds x="830" y="180" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_17q4n45_di" bpmnElement="Activity_0ur1yva">
<dc:Bounds x="630" y="180" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_12q67pq_di" bpmnElement="Event_12q67pq">
<dc:Bounds x="1032" y="202" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>