blob: 18d566e8af36f1985d8809406dcde12ab48c25d3 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_drawinglayer.hxx"
#include <drawinglayer/processor3d/cutfindprocessor3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
#include <drawinglayer/primitive3d/transformprimitive3d.hxx>
#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
#include <basegfx/polygon/b3dpolygon.hxx>
#include <basegfx/polygon/b3dpolygontools.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace processor3d
{
CutFindProcessor::CutFindProcessor(const geometry::ViewInformation3D& rViewInformation,
const basegfx::B3DPoint& rFront,
const basegfx::B3DPoint& rBack,
bool bAnyHit)
: BaseProcessor3D(rViewInformation),
maFront(rFront),
maBack(rBack),
maResult(),
maCombinedTransform(),
mbAnyHit(bAnyHit),
mbUseInvisiblePrimitiveContent(true)
{
}
void CutFindProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
{
if(getAnyHit() && maResult.size())
{
// stop processing as soon as a hit was recognized
return;
}
// it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
switch(rCandidate.getPrimitive3DID())
{
case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
{
// transform group.
const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
// remember old and transform front, back to object coordinates
const basegfx::B3DPoint aLastFront(maFront);
const basegfx::B3DPoint aLastBack(maBack);
basegfx::B3DHomMatrix aInverseTrans(rPrimitive.getTransformation());
aInverseTrans.invert();
maFront *= aInverseTrans;
maBack *= aInverseTrans;
// remember current and create new transformation; add new object transform from right side
const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
const geometry::ViewInformation3D aNewViewInformation3D(
aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
aLastViewInformation3D.getOrientation(),
aLastViewInformation3D.getProjection(),
aLastViewInformation3D.getDeviceToView(),
aLastViewInformation3D.getViewTime(),
aLastViewInformation3D.getExtendedInformationSequence());
updateViewInformation(aNewViewInformation3D);
// #i102956# remember needed back-transform for found cuts (combine from right side)
const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform);
maCombinedTransform = maCombinedTransform * rPrimitive.getTransformation();
// let break down
process(rPrimitive.getChildren());
// restore transformations and front, back
maCombinedTransform = aLastCombinedTransform;
updateViewInformation(aLastViewInformation3D);
maFront = aLastFront;
maBack = aLastBack;
break;
}
case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
{
// PolygonHairlinePrimitive3D, not used for hit test with planes, ignore. This
// means that also thick line expansion will not be hit-tested as
// PolyPolygonMaterialPrimitive3D
break;
}
case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
{
// #i97321#
// For HatchTexturePrimitive3D, do not use the decomposition since it will produce
// clipped hatch lines in 3D. It can be used when the hatch also has a filling, but for
// simplicity, just use the children which are the PolyPolygonMaterialPrimitive3D
// which define the hatched areas anyways; for HitTest this is more than adequate
const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rCandidate);
process(rPrimitive.getChildren());
break;
}
case PRIMITIVE3D_ID_HIDDENGEOMETRYPRIMITIVE3D :
{
// HiddenGeometryPrimitive3D; the default decomposition would return an empty seqence,
// so force this primitive to process it's children directly if the switch is set
// (which is the default). Else, ignore invisible content
const primitive3d::HiddenGeometryPrimitive3D& rHiddenGeometry(static_cast< const primitive3d::HiddenGeometryPrimitive3D& >(rCandidate));
const primitive3d::Primitive3DSequence& rChildren = rHiddenGeometry.getChildren();
if(rChildren.hasElements())
{
if(getUseInvisiblePrimitiveContent())
{
process(rChildren);
}
}
break;
}
case PRIMITIVE3D_ID_UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D :
{
const primitive3d::UnifiedTransparenceTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::UnifiedTransparenceTexturePrimitive3D& >(rCandidate);
const primitive3d::Primitive3DSequence rChildren = rPrimitive.getChildren();
if(rChildren.getLength())
{
if(1.0 <= rPrimitive.getTransparence())
{
// not visible, but use for HitTest
if(getUseInvisiblePrimitiveContent())
{
process(rChildren);
}
}
else if(rPrimitive.getTransparence() >= 0.0 && rPrimitive.getTransparence() < 1.0)
{
// visible; use content
process(rChildren);
}
}
break;
}
case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
{
// PolyPolygonMaterialPrimitive3D
const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
if(!maFront.equal(maBack))
{
const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon();
const sal_uInt32 nPolyCount(rPolyPolygon.count());
if(nPolyCount)
{
const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(0));
const sal_uInt32 nPointCount(aPolygon.count());
if(nPointCount > 2)
{
const basegfx::B3DVector aPlaneNormal(aPolygon.getNormal());
if(!aPlaneNormal.equalZero())
{
const basegfx::B3DPoint aPointOnPlane(aPolygon.getB3DPoint(0));
double fCut(0.0);
if(basegfx::tools::getCutBetweenLineAndPlane(aPlaneNormal, aPointOnPlane, maFront, maBack, fCut))
{
const basegfx::B3DPoint aCutPoint(basegfx::interpolate(maFront, maBack, fCut));
if(basegfx::tools::isInside(rPolyPolygon, aCutPoint, false))
{
// #i102956# add result. Do not forget to do this in the coordinate
// system the processor get started with, so use the collected
// combined transformation from processed TransformPrimitive3D's
maResult.push_back(maCombinedTransform * aCutPoint);
}
}
}
}
}
}
break;
}
default :
{
// process recursively
process(rCandidate.get3DDecomposition(getViewInformation3D()));
break;
}
}
}
} // end of namespace processor3d
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
// eof