CADSystemOCE.cpp 12.4 KB
Newer Older
mike's avatar
mike committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
////////////////////////////////////////////////////////////////////////////////
//
//  File: CADSystem.cpp
//
//  For more information, please see: http://www.nektar.info/
//
//  The MIT License
//
//  Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
//  Department of Aeronautics, Imperial College London (UK), and Scientific
//  Computing and Imaging Institute, University of Utah (USA).
//
//  License for the specific language governing rights and limitations under
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included
//  in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//
//  Description: cad object methods.
//
////////////////////////////////////////////////////////////////////////////////
35
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
mike's avatar
mike committed
36

mike turner's avatar
mike turner committed
37
#include <NekMeshUtils/CADSystem/CADSurf.h>
38 39
#include <NekMeshUtils/CADSystem/OCE/CADCurveOCE.h>
#include <NekMeshUtils/CADSystem/OCE/CADSurfOCE.h>
mike turner's avatar
mike turner committed
40 41
#include <NekMeshUtils/CADSystem/OCE/CADSystemOCE.h>
#include <NekMeshUtils/CADSystem/OCE/CADVertOCE.h>
mike's avatar
mike committed
42 43 44 45 46 47 48 49

using namespace std;

namespace Nektar
{
namespace NekMeshUtils
{

50 51
std::string CADSystemOCE::key = GetEngineFactory().RegisterCreatorFunction(
    "oce", CADSystemOCE::create, "Uses OCE as cad engine");
mike's avatar
mike committed
52 53 54

bool CADSystemOCE::LoadCAD()
{
55
    if (m_naca.size() == 0)
mike's avatar
mike committed
56
    {
mike turner's avatar
mike turner committed
57
        // not a naca profile behave normally
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
        // Takes step file and makes OpenCascade shape
        STEPControl_Reader reader;
        reader = STEPControl_Reader();
        reader.ReadFile(m_name.c_str());
        reader.NbRootsForTransfer();
        reader.TransferRoots();
        shape = reader.OneShape();
        if (shape.IsNull())
        {
            return false;
        }
    }
    else
    {
        shape = BuildNACA(m_name);
mike's avatar
mike committed
73 74
    }

mike turner's avatar
mike turner committed
75
    TopExp_Explorer explr;
mike's avatar
mike committed
76 77

    // build map of verticies
mike turner's avatar
mike turner committed
78
    for (explr.Init(shape, TopAbs_VERTEX); explr.More(); explr.Next())
mike's avatar
mike committed
79
    {
mike turner's avatar
mike turner committed
80
        TopoDS_Shape v = explr.Current();
81
        if (mapOfVerts.Contains(v))
mike turner's avatar
mike turner committed
82 83 84 85
        {
            continue;
        }
        int i = mapOfVerts.Add(v);
mike's avatar
mike committed
86 87 88 89 90 91
        AddVert(i, v);
    }

    // For each face of the geometry, get the local edges which bound it. If
    // they are valid (their type != 7), then add them to an edge map. This
    // filters out the dummy edges which OCC uses.
mike turner's avatar
mike turner committed
92
    for (explr.Init(shape, TopAbs_EDGE); explr.More(); explr.Next())
mike's avatar
mike committed
93
    {
mike turner's avatar
mike turner committed
94
        TopoDS_Shape e = explr.Current().Oriented(TopAbs_FORWARD);
95
        if (mapOfEdges.Contains(e))
mike's avatar
mike committed
96
        {
mike turner's avatar
mike turner committed
97
            continue;
mike's avatar
mike committed
98
        }
mike turner's avatar
mike turner committed
99 100
        BRepAdaptor_Curve curve = BRepAdaptor_Curve(TopoDS::Edge(e));
        if (curve.GetType() != 7)
mike's avatar
mike committed
101
        {
mike turner's avatar
mike turner committed
102
            int i = mapOfEdges.Add(e);
103
            AddCurve(i, e);
mike's avatar
mike committed
104 105 106
        }
    }

mike turner's avatar
mike turner committed
107
    for (explr.Init(shape, TopAbs_FACE); explr.More(); explr.Next())
mike's avatar
mike committed
108
    {
Michael Turner's avatar
Michael Turner committed
109
        TopoDS_Shape f = explr.Current();
mike turner's avatar
mike turner committed
110 111
        ASSERTL0(!mapOfFaces.Contains(f), "duplicated faces");
        int i = mapOfFaces.Add(f);
mike's avatar
mike committed
112

mike turner's avatar
mike turner committed
113
        AddSurf(i, f);
mike's avatar
mike committed
114 115 116 117 118
    }

    // attempts to identify properties of the vertex on the degen edge
    for (int i = 1; i <= mapOfFaces.Extent(); i++)
    {
Michael Turner's avatar
Michael Turner committed
119
        TopoDS_Shape face = mapOfFaces.FindKey(i).Oriented(TopAbs_FORWARD);
mike's avatar
mike committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

        TopTools_IndexedMapOfShape localEdges;
        TopExp::MapShapes(face, TopAbs_EDGE, localEdges);

        for (int j = 1; j <= localEdges.Extent(); j++)
        {
            TopoDS_Shape edge = localEdges.FindKey(j);
            if (BRep_Tool::Degenerated(TopoDS::Edge(edge)))
            {
                gp_Pnt2d p1, p2;

                BRep_Tool::UVPoints(TopoDS::Edge(edge), TopoDS::Face(face), p1,
                                    p2);

                m_verts[mapOfVerts.FindIndex(TopExp::FirstVertex(
                            TopoDS::Edge(edge), Standard_True))]
                    ->SetDegen(i, m_surfs[i], (p1.X() + p2.X()) / 2.0,
                               (p1.Y() + p2.Y()) / 2.0);
            }
        }
    }

    // This checks that all edges are bound by two surfaces, sanity check.
mike turner's avatar
mike turner committed
143
    if (!m_2d)
mike's avatar
mike committed
144
    {
mike turner's avatar
mike turner committed
145 146
        map<int, CADCurveSharedPtr>::iterator it;
        for (it = m_curves.begin(); it != m_curves.end(); it++)
147
        {
mike turner's avatar
mike turner committed
148 149
            ASSERTL0(it->second->GetAdjSurf().size() == 2,
                     "curve is not joined to 2 surfaces");
150
        }
mike's avatar
mike committed
151
    }
mike turner's avatar
mike turner committed
152

mike's avatar
mike committed
153 154 155 156 157 158 159
    return true;
}

void CADSystemOCE::AddVert(int i, TopoDS_Shape in)
{
    CADVertSharedPtr newVert = GetCADVertFactory().CreateInstance(key);

160
    boost::static_pointer_cast<CADVertOCE>(newVert)->Initialise(i, in);
mike's avatar
mike committed
161 162 163 164

    m_verts[i] = newVert;
}

mike turner's avatar
mike turner committed
165
void CADSystemOCE::AddCurve(int i, TopoDS_Shape in)
mike's avatar
mike committed
166 167
{
    CADCurveSharedPtr newCurve = GetCADCurveFactory().CreateInstance(key);
168
    boost::static_pointer_cast<CADCurveOCE>(newCurve)->Initialise(i, in);
mike's avatar
mike committed
169

mike turner's avatar
mike turner committed
170 171 172
    TopoDS_Vertex fv = TopExp::FirstVertex(TopoDS::Edge(in));
    TopoDS_Vertex lv = TopExp::LastVertex(TopoDS::Edge(in));

mike's avatar
mike committed
173
    vector<CADVertSharedPtr> vs;
mike turner's avatar
mike turner committed
174 175 176 177
    vs.push_back(m_verts[mapOfVerts.FindIndex(fv)]);
    vs.push_back(m_verts[mapOfVerts.FindIndex(lv)]);
    newCurve->SetVert(vs);

mike's avatar
mike committed
178 179 180
    m_curves[i] = newCurve;
}

mike turner's avatar
mike turner committed
181
void CADSystemOCE::AddSurf(int i, TopoDS_Shape in)
mike's avatar
mike committed
182 183
{
    CADSurfSharedPtr newSurf = GetCADSurfFactory().CreateInstance(key);
mike turner's avatar
mike turner committed
184
    boost::static_pointer_cast<CADSurfOCE>(newSurf)->Initialise(i, in);
mike's avatar
mike committed
185

186
    // do the exploration on forward oriented
Michael Turner's avatar
Michael Turner committed
187
    TopoDS_Shape face = in.Oriented(TopAbs_FORWARD);
mike turner's avatar
mike turner committed
188
    TopTools_IndexedMapOfShape mapOfWires;
Michael Turner's avatar
Michael Turner committed
189
    TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires);
mike turner's avatar
mike turner committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    vector<EdgeLoopSharedPtr> edgeloops;
    // now we acutally analyse the loops for cad building
    for (int j = 1; j <= mapOfWires.Extent(); j++)
    {
        EdgeLoopSharedPtr edgeloop = EdgeLoopSharedPtr(new EdgeLoop);

        TopoDS_Shape wire = mapOfWires.FindKey(j);

        BRepTools_WireExplorer exp;

        exp.Init(TopoDS::Wire(wire));

        while (exp.More())
        {
            TopoDS_Shape edge = exp.Current();

            if (mapOfEdges.Contains(edge))
            {
                int e = mapOfEdges.FindIndex(edge);
                edgeloop->edges.push_back(m_curves[e]);
210 211 212
                edgeloop->edgeo.push_back(exp.Orientation() == TopAbs_FORWARD
                                              ? eForwards
                                              : eBackwards);
mike turner's avatar
mike turner committed
213 214 215 216 217 218
            }
            exp.Next();
        }
        edgeloops.push_back(edgeloop);
    }

mike's avatar
mike committed
219
    int tote = 0;
mike turner's avatar
mike turner committed
220
    for (int k = 0; k < edgeloops.size(); k++)
mike's avatar
mike committed
221
    {
mike turner's avatar
mike turner committed
222
        tote += edgeloops[k]->edges.size();
mike's avatar
mike committed
223 224 225
    }

    ASSERTL0(tote != 1, "cannot handle periodic curves");
mike turner's avatar
mike turner committed
226

mike turner's avatar
mike turner committed
227 228
    CADSurf::OrientateEdges(newSurf, edgeloops);
    newSurf->SetEdges(edgeloops);
mike turner's avatar
mike turner committed
229 230

    // now the loops are orientated, tell the curves how they are
mike turner's avatar
mike turner committed
231
    for (int k = 0; k < edgeloops.size(); k++)
mike turner's avatar
mike turner committed
232
    {
mike turner's avatar
mike turner committed
233
        for (int j = 0; j < edgeloops[k]->edges.size(); j++)
mike turner's avatar
mike turner committed
234
        {
235 236
            edgeloops[k]->edges[j]->SetAdjSurf(
                make_pair(newSurf, edgeloops[k]->edgeo[j]));
mike turner's avatar
mike turner committed
237 238 239 240
        }
    }

    m_surfs[i] = newSurf;
mike's avatar
mike committed
241 242 243 244 245 246 247 248 249 250 251 252 253 254
}

Array<OneD, NekDouble> CADSystemOCE::GetBoundingBox()
{
    Array<OneD, NekDouble> bound(6);
    bound[0] = numeric_limits<double>::max(); // xmin
    bound[1] = numeric_limits<double>::min(); // xmax
    bound[2] = numeric_limits<double>::max(); // ymin
    bound[3] = numeric_limits<double>::min(); // ymax
    bound[4] = numeric_limits<double>::max(); // zmin
    bound[5] = numeric_limits<double>::min(); // zmax

    for (int i = 1; i <= m_curves.size(); i++)
    {
mike turner's avatar
mike turner committed
255
        CADCurveSharedPtr c = GetCurve(i);
mike's avatar
mike committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
        Array<OneD, NekDouble> ends = c->GetMinMax();

        bound[0] = min(bound[0], min(ends[0], ends[3]));
        bound[1] = max(bound[1], max(ends[0], ends[3]));

        bound[2] = min(bound[2], min(ends[1], ends[4]));
        bound[3] = max(bound[3], max(ends[1], ends[4]));

        bound[4] = min(bound[4], min(ends[2], ends[5]));
        bound[5] = max(bound[5], max(ends[2], ends[5]));
    }

    return bound;
}

271 272 273
TopoDS_Shape CADSystemOCE::BuildNACA(string naca)
{
    ASSERTL0(naca.length() == 4, "not a 4 digit code");
274 275 276
    vector<NekDouble> data;
    ParseUtils::GenerateUnOrderedVector(m_naca.c_str(), data);
    ASSERTL0(data.size() == 5, "not a vaild domain");
277

mike turner's avatar
mike turner committed
278 279 280 281 282 283
    int n       = boost::lexical_cast<int>(naca);
    NekDouble T = (n % 100) / 100.0;
    n /= 100;
    NekDouble P = (n % 10) / 10.0;
    n /= 10;
    NekDouble M = (n % 10) / 100.0;
284

Michael Turner's avatar
working  
Michael Turner committed
285 286 287
    int np = 25;

    Array<OneD, NekDouble> xc(np);
mike turner's avatar
mike turner committed
288 289
    NekDouble dtheta = M_PI / (np - 1);
    for (int i = 0; i < np; i++)
290
    {
mike turner's avatar
mike turner committed
291
        xc[i] = (1.0 - cos(i * dtheta)) / 2.0;
292 293
    }

Michael Turner's avatar
working  
Michael Turner committed
294
    Array<OneD, NekDouble> yc(np), dyc(np);
mike turner's avatar
mike turner committed
295
    for (int i = 0; i < np; i++)
296
    {
mike turner's avatar
mike turner committed
297
        if (xc[i] < P)
298
        {
mike turner's avatar
mike turner committed
299
            yc[i]  = M / P / P * (2.0 * P * xc[i] - xc[i] * xc[i]);
300 301 302 303
            dyc[i] = 2.0 * M / P / P * (P - xc[i]);
        }
        else
        {
mike turner's avatar
mike turner committed
304 305
            yc[i] = M / (1.0 - P) / (1.0 - P) *
                    (1.0 - 2.0 * P + 2.0 * P * xc[i] - xc[i] * xc[i]);
306 307 308 309
            dyc[i] = 2.0 * M / (1.0 - P) / (1.0 - P) * (P - xc[i]);
        }
    }

Michael Turner's avatar
working  
Michael Turner committed
310
    Array<OneD, NekDouble> yt(np);
mike turner's avatar
mike turner committed
311
    for (int i = 0; i < np; i++)
312
    {
mike turner's avatar
mike turner committed
313 314 315 316
        yt[i] =
            T / 0.2 * (0.2969 * sqrt(xc[i]) - 0.1260 * xc[i] -
                       0.3516 * xc[i] * xc[i] + 0.2843 * xc[i] * xc[i] * xc[i] -
                       0.1015 * xc[i] * xc[i] * xc[i] * xc[i]);
317 318
    }

mike turner's avatar
mike turner committed
319
    Array<OneD, NekDouble> x(2 * np - 1), y(2 * np - 1);
320
    int l = 0;
mike turner's avatar
mike turner committed
321
    for (int i = np - 1; i >= 0; i--, l++)
322 323 324 325 326 327
    {
        NekDouble theta = atan(dyc[i]);

        x[l] = xc[i] - yt[i] * sin(theta);
        y[l] = yc[i] + yt[i] * cos(theta);
    }
mike turner's avatar
mike turner committed
328
    for (int i = 1; i < np; i++)
329 330 331
    {
        NekDouble theta = atan(dyc[i]);

mike turner's avatar
mike turner committed
332 333
        x[i + np - 1] = xc[i] + yt[i] * sin(theta);
        y[i + np - 1] = yc[i] - yt[i] * cos(theta);
334 335
    }

mike turner's avatar
mike turner committed
336
    TColgp_Array1OfPnt pointArray(0, 2 * np - 2);
337

mike turner's avatar
mike turner committed
338
    for (int i = 0; i < 2 * np - 1; i++)
339
    {
mike turner's avatar
mike turner committed
340
        pointArray.SetValue(i, gp_Pnt(x[i] * 1000.0, y[i] * 1000.0, 0.0));
341 342
    }

Michael Turner's avatar
working  
Michael Turner committed
343
    GeomAPI_PointsToBSpline spline(pointArray);
344 345 346 347
    Handle(Geom_BSplineCurve) curve = spline.Curve();

    BRepBuilderAPI_MakeEdge areoEdgeBuilder(curve);
    TopoDS_Edge aeroEdge = areoEdgeBuilder.Edge();
Dave Moxey's avatar
Dave Moxey committed
348
    BRepBuilderAPI_MakeEdge aeroTEBuilder(
mike turner's avatar
mike turner committed
349 350
        gp_Pnt(x[0] * 1000.0, y[0] * 1000.0, 0.0),
        gp_Pnt(x[2 * np - 2] * 1000.0, y[2 * np - 2] * 1000.0, 0.0));
351 352 353 354 355
    TopoDS_Edge TeEdge = aeroTEBuilder.Edge();

    BRepBuilderAPI_MakeWire aeroWireBuilder(aeroEdge, TeEdge);
    TopoDS_Wire aeroWire = aeroWireBuilder.Wire();

356
    gp_Trsf transform;
mike turner's avatar
mike turner committed
357 358
    gp_Ax1 rotAx(gp_Pnt(500.0, 0.0, 0.0), gp_Dir(gp_Vec(0.0, 0.0, -1.0)));
    transform.SetRotation(rotAx, data[4] / 180.0 * M_PI);
359 360 361
    TopLoc_Location mv(transform);
    aeroWire.Move(mv);

mike turner's avatar
mike turner committed
362 363 364
    BRepBuilderAPI_MakeEdge domInlBuilder(
        gp_Pnt(data[0] * 1000.0, data[1] * 1000.0, 0.0),
        gp_Pnt(data[0] * 1000.0, data[3] * 1000.0, 0.0));
365
    TopoDS_Edge inlEdge = domInlBuilder.Edge();
366

mike turner's avatar
mike turner committed
367 368 369
    BRepBuilderAPI_MakeEdge domTopBuilder(
        gp_Pnt(data[0] * 1000.0, data[3] * 1000.0, 0.0),
        gp_Pnt(data[2] * 1000.0, data[3] * 1000.0, 0.0));
370
    TopoDS_Edge topEdge = domTopBuilder.Edge();
371

mike turner's avatar
mike turner committed
372 373 374
    BRepBuilderAPI_MakeEdge domOutBuilder(
        gp_Pnt(data[2] * 1000.0, data[3] * 1000.0, 0.0),
        gp_Pnt(data[2] * 1000.0, data[1] * 1000.0, 0.0));
375
    TopoDS_Edge outEdge = domOutBuilder.Edge();
Michael Turner's avatar
Michael Turner committed
376

mike turner's avatar
mike turner committed
377 378 379
    BRepBuilderAPI_MakeEdge domBotBuilder(
        gp_Pnt(data[2] * 1000.0, data[1] * 1000.0, 0.0),
        gp_Pnt(data[0] * 1000.0, data[1] * 1000.0, 0.0));
380 381 382 383 384 385 386 387
    TopoDS_Edge botEdge = domBotBuilder.Edge();

    BRepBuilderAPI_MakeWire domWireBuilder(inlEdge, topEdge, outEdge, botEdge);
    TopoDS_Wire domWire = domWireBuilder.Wire();

    BRepBuilderAPI_MakeFace face(domWire, true);
    face.Add(aeroWire);

388 389 390 391 392
    ShapeFix_Face sf(face.Face());
    sf.FixOrientation();


    return sf.Face();
393
}
mike's avatar
mike committed
394 395
}
}